这两个异步实现之间的区别

时间:2016-06-02 05:19:45

标签: c# asynchronous async-await task-parallel-library

我正在使用EF的异步方法从数据库中获取数据。大部分时间都很好。我最近遇到了一些ObjectContextDisposed异常,我很好奇为什么我的解决方案有效:

以下是投放ObjectContextDisposed的原始代码:

public Task<List<string>> GetEventParameterMru(EventParameter parameter, int count = 20)
{
    using (var repo = new ConfigurationRepository())
    {
        return repo.GetEventParameterMRU(_CurrentWorkpack, parameter, count)             
    }
}

这是我的新代码,不会抛出:

public async Task<List<string>> GetEventParameterMru(EventParameter parameter, int count = 20)
{
    using (var repo = new ConfigurationRepository())
    {
        var result = await repo.GetEventParameterMRU(_CurrentWorkpack, parameter, count);
        return result;
    }
}

有人可以向我解释一下有什么区别,为什么会有效?

仅供参考,在我使用此方法的所有用法中,我致电await GetEventParameterMru()

由于

4 个答案:

答案 0 :(得分:5)

GetEventParameterMRU显然是一种启动Task来检索某些数据的方法。因此,在GetEventParameterMRU的所有操作都已完成之前,repo会返回。

两个版本的代码都使用using语句,该语句被转换为try/finally块。在finally区块中,repo处置

在您的第一个版本中,在调用GetEventParameterMRU(启动任务)后返回 immediatly 。这意味着repo在使用Task的{​​{1}}仍在运行时会立即处理。因此,当repo访问Task时,您会收到

  

的ObjectDisposedException

在第二个版本中,您使用repo。因此,编译器将您的整个方法转换为状态机。该方法在await语句处将控制权返回给其调用者,但没有传递await块。
finally完成后,在Task语句后继续执行您的方法 因此await 仅在repo完成时处理。所以你没有得到Task

答案 1 :(得分:2)

以下是我对初始代码审核的理解:

在第一个中,Async实施不是using block,但最后repo.Dispose()仍会从最终调用Task is executed的{​​{1}}返回一个任务(假设它由调用者完成,但即使对于方法 - GetEventParameterMRU启动它也是如此),在那个时间处置repo是非常可行的,但仍然是操作,因此异常< / p>

在第二个问题中,情况并非如此,即使它已经释放了UI /调用线程,直到并且除非完成以下操作:

await repo.GetEventParameterMRU(_CurrentWorkpack, parameter, count)

它不会调用repo.Dispose(),从而完全避免ObjectContextDisposed问题

答案 2 :(得分:1)

让我为你翻译一下:

第一个:

Create repository
Start GetEventParameterMRU on repository as Task
Dispose repository
return Task, that is still working with repository

第二个:

Create repository
Start GetEventParameterMRU on repository as Task
Wait for Task to finish to get result
Dispose repository
return result

正如你所看到的,问题在这里很清楚。

答案 3 :(得分:0)

我认为这与第一个没有显式捕获当前SynchronizationContext的代码有关,而等待DOES明确地捕获它。

进一步阅读:

https://msdn.microsoft.com/en-us/magazine/gg598924.aspx