UOW - Une deuxième opération a démarré sur ce contexte avant la fin d'une opération asynchrone précédente
Je suis en train de code suivant, il a deux parties, l'une est la navigation via le prisme.
Lorsque la navigation est autorisée je suis en train de créer une profonde charger de manière asynchrone, mais à chaque fois avec un nouveau contexte. Plus tard dans le code je voudrais annuler en attente de navigation qui ne sont pas finis ce chargement, mais le code ci-dessous n'a pas de travail même si l'annulation est une question pour plus tard 😉
de navigation logique : pas de problèmes ici
public void OnNavigatedTo(NavigationContext navigationContext)
{
int relatieId = (int)navigationContext.Parameters["RelatieId"];
if (_relatie != null && _relatie.RelatieId == relatieId) return;
loadRelatieAsync(relatieId);
}
public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
{
bool navigationAllowed = true;
continuationCallback(navigationAllowed);
}
profond de chargement logique:
private async Task loadRelatieAsync(int relatieId)
{
try
{
await Task.Run(async () =>
{
_unitOfWork = _UnitOfWorkFactory.createUnitOfWorkAsync();
IEnumerable<Relatie> relaties = await getRelatieAsync(_unitOfWork, relatieId).ConfigureAwait(true);
_relatieTypeTypes = await getRelatieTypeTypesAsync(_unitOfWork, relatieId).ConfigureAwait(true);
_relatie = relaties.FirstOrDefault();
_unitOfWork.Dispose();
}).ConfigureAwait(true);
processRelatie(_relatie);
processRelatieTypes(_relatie, _relatieTypeTypes);
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
throw;
}
}
private async Task<IEnumerable<Relatie>> getRelatieAsync(IUnitOfWorkAsync unitOfWork, int relatieId)
{
IEnumerable<Relatie> relaties = null;
try
{
IRepositoryAsync<Relatie> relatieRepository = unitOfWork.RepositoryAsync<Relatie>();
relaties = await relatieRepository
.Query(r => r.RelatieId == relatieId)
.Include(i => i.BegrafenisOndernemer)
.SelectAsync()
.ConfigureAwait(false);
IRepositoryAsync<Adres> adresRepository = unitOfWork.RepositoryAsync<Adres>();
//exception is thrown after executing following line
var adressen = await adresRepository
.Query(r => r.RelatieId == relatieId)
.Include(i => i.AdresType)
.SelectAsync()
.ConfigureAwait(false);
_relatieTypeRepository = unitOfWork.RepositoryAsync<RelatieType>();
var relatieTypes = await _relatieTypeRepository
.Query(r => r.RelatieId == relatieId)
.SelectAsync()
.ConfigureAwait(false);
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);//exception is shown here
throw;
}
return relaties;
}
private async Task<IEnumerable<RelatieTypeType>> getRelatieTypeTypesAsync(IUnitOfWorkAsync unitOfWork, int relatieId)
{
IEnumerable<RelatieTypeType> relatieTypeTypes = null;
try
{
IRepositoryAsync<RelatieTypeType> relatieTypeTypeRepository =
unitOfWork.RepositoryAsync<RelatieTypeType>();
relatieTypeTypes = await relatieTypeTypeRepository
.Query()
.SelectAsync()
.ConfigureAwait(false);
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
throw;
}
return relatieTypeTypes;
}
Je continue à faire des exceptions si j'ai oublié d'attendre, mais ce n'est jamais le cas.
J'utilise aussi configureawait(vrai) correctement chaque fois que je veux continuation sur le thread GUI. Mais je reçois cette erreur dans le deeploading logique. L'unité de travail et référentiel des classes également utiliser l'async attendent mécanisme, mais là aussi je suis en attente correctement.
Une deuxième opération a commencé ce contexte, avant une précédente opération asynchrone terminé. Utiliser "attendre" pour s'assurer que toutes les opérations asynchrones ont terminé avant d'appeler une autre méthode sur ce contexte. Tous les membres de l'instance ne sont pas garantis pour être thread-safe.
Modifier (retiré de l'enregistreur de code afin de réduire la taille du code)
source d'informationauteur Philip Stuyck
Vous devez vous connecter pour publier un commentaire.
Le problème est que ce code :
la UnitOfWork est une variable d'instance, lorsque le scénario commence un deuxième temps, elle est remplacée par une nouvelle instance. La déjà en cours d'exécution scénario utilise ensuite cette nouvelle UnitOfWork au lieu de son propre, car il est écrasé.
Pas si facile à repérer, mais une simple condition de course.
Je l'ai trouvé par le remplacement de toutes les variables d'instance par les variables locales et puis le problème disappaered.
Ce n'est probablement pas la réponse, mais un aspect général plus de votre code.
But principal de async/await est de garder le Thread courant disponible. Cela permet de ne pas bloquer le Thread d'INTERFACE utilisateur et de maintien de la réactivité de votre Application.
Vous êtes déjà faire en sorte que votre profond de chargement qui se passe sur un pool de threads thread, parce que vous le lancez entièrement en utilisant Tâche.Run(). Vous pouvez probablement obtenir autour de la plupart de vos problèmes à l'aide de la valeur par défaut méthodes synchrones de EntityFramework dans votre mécanisme de chargement.
Dans un premier coup d'œil, votre code ressemble fine comme des appels asynchrones. Peut-être que votre profond de chargement est déclenché plusieurs fois?