Closed CursedMun closed 3 years ago
It seems the same as #56.
Probably, the error will go away with ToList()
at foreach
.
foreach (var documentChange in snapshot.DocumentChanges.ToList())
{
...
}
However, you should not use Result
because the main thread may be locked and use await instead.
var fichaLinhasSnapshot = await CrossCloudFirestore.Current.Instance
.Collection("FichaLinhas")
.WhereEqualsTo("numeroFicha", document.Numero)
.GetAsync();
this.dataManager.Documents.Last().ListOfDocLines = fichaLinhasSnapshot.ToObjects<DocumentLines>().ToList();
var fichaServicosSnapshot = await CrossCloudFirestore.Current.Instance
.Collection("FichaServicos")
.WhereEqualsTo("numeroFicha", document.Numero)
.GetAsync();
this.dataManager.Documents.Last().ListOfDocServices = fichaServicosSnapshot.ToObjects<DocumentService>().ToList();
Otherwise, how about trying the following because I think there is no need to get FichaLinhas
or FichaServicos
sequentially and call NotifyDataSetChanged()
in every loop.
CrossCloudFirestore.Current
.Instance
.Collection("Ficha")
.WhereEqualsTo("UtilizadorAtribuido", GlobalVars.USER_INFO.Name)
.WhereEqualsTo("FichaFechada", false)
.OrderBy("id", false)
.AddSnapshotListener(async (snapshot, error) =>
{
var tasks = new List<Task>();
foreach (var documentChange in snapshot.DocumentChanges)
{
switch (documentChange.Type)
{
case DocumentChangeType.Added:
var document = documentChange.Document.ToObject<Document>();
this.dataManager.Documents.Add(document);
document.Id = documentChange.Document.Id;
tasks.Add(Task.Run(async () =>
{
var fichaLinhasSnapshot = await CrossCloudFirestore.Current.Instance
.Collection("FichaLinhas")
.WhereEqualsTo("numeroFicha", document.Numero)
.GetAsync();
document.ListOfDocLines = fichaLinhasSnapshot.ToObjects<ListOfDocLines>().ToList();
var fichaServicosSnapshot = await CrossCloudFirestore.Current.Instance
.Collection("FichaServicos")
.WhereEqualsTo("numeroFicha", document.Numero)
.GetAsync();
document.ListOfDocServices = fichaServicosSnapshot.ToObjects<DocumentService>().ToList();
}));
break;
case DocumentChangeType.Modified:
break;
case DocumentChangeType.Removed:
// Document Removed
var docToRemove = documentChange.Document.Id;
if (dataManager.Documents.Exists(x => x.Id == docToRemove))
{
dataManager.Documents.Remove(dataManager.Documents.Where(x => x.Id == docToRemove).First());
}
break;
}
}
await Task.WhenAll(tasks);
dataAdapter.NotifyDataSetChanged();
});
Was having a similar issue with
foreach (IDocumentSnapshot row in postArray.Documents)
{
}
Can confirm changing to:
foreach (IDocumentSnapshot row in postArray.Documents.ToList())
{
}
Fixed the issue, looks to be that when numerous calls from numerous pages in the application are fighting to access firebase through the same libraries, the application is disposing of the .Documents
IEnumerable before the loop has a chance to finish. Seems like using .ToList()
and creating another reference to the data that isn't within the libraries fixes the issue. (Correct me if I am wrong)
Edit:
The original error has gone away, but another error now appears sometimes and other times the application is fine.
System.ObjectDisposedException
Cannot access a disposed object.
Object name: 'Firebase.Firestore.QueryDocumentSnapshot'
See issue #84
So the problem is when I execute that part of the code with await before the queries it woks properly but at the last document it throws that error
System.ArgumentException: 'Handle must be valid. Parameter name: instance'
and closesvar query = CrossCloudFirestore.Current.Instance.Collection("FichaLinhas").WhereEqualsTo("numeroFicha", this.dataManager.Documents.Last().Numero).GetAsync(); this.dataManager.Documents.Last().ListOfDocLines = query.Result.ToObjects().ToList();
query = CrossCloudFirestore.Current.Instance.Collection("FichaServicos").WhereEqualsTo("numeroFicha",
this.dataManager.Documents.Last().Numero).GetAsync();
this.dataManager.Documents.Last().ListOfDocServices = query.Result.ToObjects().ToList();
If I execute the await before the queries it just freezes at the query and doesn't go further If I execute without that part of the code it works
Whole Code ->