简体   繁体   English

同步调用异步方法

[英]Invoking an async method synchronously

I need to call synchronously an asynchronous method for reasons out of my control. 出于我无法控制的原因,我需要同步调用异步方法。 I'm developing a library, that uses another library that works asynchronously and I need use it from an implementation of the Stream class. 我正在开发一个库,它使用另一个异步工作的库,我需要从Stream类的实现中使用它。 Such class contains synchronous and asynchronous methods, and I am feeling uneasy about the synchronous ones: 这样的类包含同步和异步方法,我对同步方法感到不安:

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);
}

I have been reading How would I run an async Task<T> method synchronously? 我一直在阅读如何同步运行异步Task <T>方法? , in particular this answer , and in the comments @Stephen Cleary states that the solution is not good, since some ASP.NET parts expect a AspNetSynchronizationContext . ,特别是这个答案 ,在评论中@Stephen Cleary表示解决方案并不好,因为一些ASP.NET部分需要一个AspNetSynchronizationContext I am developing a library, so I do not know where my classes are going to be called from. 我正在开发一个库,所以我不知道我的类将从何处调用。

What would be the safest way of invoking an async method synchronously? 同步调用异步方法最安全的方法是什么?

Stephen Toub covers all the various approaches with their corresponding drawbacks on his blog. Stephen Toub在他的博客中涵盖了所有各种方法及其相应的缺点

There are only two general-purpose solutions, neither of which is ideal: 只有两种通用解决方案,两者都不理想:

  1. Duplicate the logic in your layer; 复制图层中的逻辑; have your synchronous methods call the synchronous methods in the library. 让您的同步方法调用库中的同步方法。 (This assumes that the library has synchronous methods as well as asynchronous). (这假定库具有同步方法以及异步)。
  2. Block on the returned task, similar to your example code. 阻止返回的任务,类似于您的示例代码。 This assumes that the library always uses ConfigureAwait(false) , an assumption that is out of your control. 这假设库始终使用ConfigureAwait(false) ,这是一个不受控制的假设。 If the library is context-free, then it may be safer to throw the asynchronous invocation into a Task.Run and block on that task instead. 如果库是无上下文的,那么将异步调用抛出到Task.Run并阻塞该任务可能更安全。 Also, ensure you unwrap exceptions when blocking on a task, since Wait or Result will wrap exceptions in an AggregateException . 此外,确保在阻止任务时解除异常,因为WaitResult将在AggregateException包装异常。

Both of these solutions have somewhat serious maintenance problems. 这两种解决方案都存在一些严重的维护问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM