同步调用异步方法

时间:2014-02-24 12:13:28

标签: c# asynchronous async-await synchronizationcontext

我需要同步调用异步方法,原因是我无法控制。我正在开发一个库,它使用另一个异步工作的库,我需要在Stream类的实现中使用它。这样的类包含同步和异步方法,我对同步方法感到不安:

public override sealed int Read(byte[] buffer, int offset, int count)
{ 
    // potential deadlock on single threaded synchronization context
    return ReadAsync(buffer, offset, count).Result;
}

public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
   return await _lib.ReadAsync(buffer,offset,count);
}

我一直在阅读How would I run an async Task<T> method synchronously?,特别是this answer,在评论中@Stephen Cleary表示解决方案并不好,因为有些ASP.NET部分需要AspNetSynchronizationContext。我正在开发一个库,所以我不知道我的类将从何处调用。

同步调用异步方法最安全的方法是什么?

1 个答案:

答案 0 :(得分:3)

Stephen Toub covers all the various approaches with their corresponding drawbacks在他的博客上。

只有两种通用解决方案,两者都不理想:

  1. 复制图层中的逻辑;让您的同步方法调用库中的同步方法。 (这假设库具有同步方法以及异步)。
  2. 阻止返回的任务,类似于您的示例代码。这假定库始终使用ConfigureAwait(false),这是一个不受您控制的假设。如果库是无上下文的,那么将异步调用抛出到Task.Run并阻塞该任务可能更安全。此外,确保在阻止任务时解除例外,因为WaitResult将在AggregateException中包含例外。
  3. 这两种解决方案都存在一些严重的维护问题。