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

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

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

有没有安全的方法来保持同步签名和调用异步实现?

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

我强烈鼓励你不要这样做

首先,读取我应该为异步方法公开同步包装器吗? 我应该为同步方法公开异步包装器吗? 作者:Stephan Toub。

我不这样做的主要原因:

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

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

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

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

我通常使用异步版本包装同步调用并将其作为任务处理。 如果这些同步方法可以使用.NET方法的异步版本,我会尝试尽可能“深入”。