UOW – 在上一次异步操作完成之前,在此上下文中启动了第二个操作

我正在尝试下面的代码,它有两个部分,一个是通过棱镜导航。 当允许导航时,我以异步方式开始深度加载,但每次都使用新的上下文。 在以后的代码中,我想要取消未完成此加载的待处理导航,但下面的代码甚至不起作用,因此取消是稍后的事情;-)

导航逻辑:这里没问题

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 continuationCallback) { bool navigationAllowed = true; continuationCallback(navigationAllowed); } 

深度加载逻辑:

 private async Task loadRelatieAsync(int relatieId) { try { await Task.Run(async () => { _unitOfWork = _UnitOfWorkFactory.createUnitOfWorkAsync(); IEnumerable 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> getRelatieAsync(IUnitOfWorkAsync unitOfWork, int relatieId) { IEnumerable relaties = null; try { IRepositoryAsync relatieRepository = unitOfWork.RepositoryAsync(); relaties = await relatieRepository .Query(r => r.RelatieId == relatieId) .Include(i => i.BegrafenisOndernemer) .SelectAsync() .ConfigureAwait(false); IRepositoryAsync adresRepository = unitOfWork.RepositoryAsync(); //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(); 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> getRelatieTypeTypesAsync(IUnitOfWorkAsync unitOfWork, int relatieId) { IEnumerable relatieTypeTypes = null; try { IRepositoryAsync relatieTypeTypeRepository = unitOfWork.RepositoryAsync(); relatieTypeTypes = await relatieTypeTypeRepository .Query() .SelectAsync() .ConfigureAwait(false); } catch (Exception Ex) { MessageBox.Show(Ex.Message); throw; } return relatieTypeTypes; } 

我不断得到例外,好像我忘了等待,但事实并非如此。 每当我想在GUI线程上继续时,我也正确使用configureawait(true)。 但我一直在深度加载逻辑中得到这个错误。 工作单元和存储库类也使用异步等待机制,但我正在等待正确。

在先前的异步操作完成之前,在该上下文上开始第二个操作。 使用’await’确保在此上下文上调用另一个方法之前已完成任何异步操作。 任何实例成员都不保证是线程安全的。

编辑 (删除记录器代码以减少代码大小)

问题是这段代码:

 _unitOfWork = _UnitOfWorkFactory.createUnitOfWorkAsync(); IEnumerable relaties = await getRelatieAsync(_unitOfWork, relatieId).ConfigureAwait(true); _relatieTypeTypes = await getRelatieTypeTypesAsync(_unitOfWork, relatieId).ConfigureAwait(true); _relatie = relaties.FirstOrDefault(); _unitOfWork.Dispose(); 

UnitOfWork是一个实例变量,当场景第二次被新实例覆盖时。 已经执行的场景然后使用新的UnitOfWork而不是它自己的,因为它被覆盖了。 不是那么容易发现,而是简单的竞争条件。 我通过用局部变量替换所有实例变量来找到它,然后问题就失败了。

这可能不是答案,而是对代码的一般看法。

async / await的主要目的是保持当前线程可用。 这有助于阻止UI线程并保持您的应用程序响应。

您已经确定深度加载发生在ThreadPool线程上,因为您完全使用Task.Run()启动它。 您可以通过在加载机制中使用EntityFramework的默认同步方法来解决大多数问题。

初看起来,您的代码在异步调用中看起来很好 。 也许您的深度加载会被多次触发?