如何安全地混合同步和异步代码?

时间:2014-06-18 22:59:34

标签: c# .net asynchronous async-await deadlock

我有这个纯粹同步的库。它暴露了同步方法,我让客户使用它。

我将底层实现更改为异步和公开异步方法,以便任何想要使用它的人。但现在我有很多复制代码。异步代码似乎表现更好。我希望现有客户能够利用它,我想消除代码重复。

是否有任何安全的方法来保持同步签名并调用异步实现?

我在打电话时特别害怕死锁.Result和.Wait。

2 个答案:

答案 0 :(得分:16)

我强烈鼓励你不要这样做

首先,阅读Stephan Toub的Should I expose synchronous wrappers for asynchronous methods?Should I expose asynchronous wrappers for synchronous methods?

我不会这样做的主要原因是:

  1. 通过异步同步 - 如你所说,死锁。在调用链中更高或更低,在异步上使用ResultWait可能是有风险的业务。这实际上取决于您运行的平台(ASP.NET,UI,控制台),因为每个平台的行为都有所不同(即使使用ConfigureAwait(false)时)

  2. 异步同步 - 可扩展性。一旦我看到异步端点,我认为它是纯粹的异步,对我来说,因为API的消费者意味着没有任何线程在“我背后”旋转。如果您的用户假设相同,则发现每次调用异步方法时,使用线程池线程会在尝试向外扩展时严重损害性能。如果用户想要使用Task.Run包装同步方法,则将其留给他们进行调用,并判断他们将如何影响他们的应用

    < / LI>

答案 1 :(得分:3)

尝试从下往上开始,或者遇到死锁(

控制台应用程序与Web和UI应用程序的行为方式不同,如果它们未正确处理,它们将如何处理死锁。如果您正在使用MVC,请使用异步任务ActionResult并使用async和await在Task.Run(()=&gt; SYNCCODE)上包装特定的同步调用。与UI代码类似的过程,使用async / await对事件方法(例如Click事件处理程序)。

我通常使用异步版本包装同步调用并将其作为任务处理。如果这些同步方法可以使用.NET方法的异步版本,我会尝试更深入地了解&#34;在可能的情况。