从同步方法调用异步方法

Liz*_*izP 7 c# asynchronous

我看到很多关于从同步方法调用异步方法的问题,例如:How to call asynchronous method from synchronous method in C#?

我理解这些解决方案,但是,通过实验,我发现我不需要添加.Wait()orTask.Run(async () => await MyAsyncMethod())来使其同步运行。我有一个从数据库中提取信息的 get 方法。

我的代码如下,当我运行时,它会等待var task = GetItemAsync(),然后我从数据库中得到正确的结果。我发现很难相信数据库调用可以在代码继续运行之前返回,这似乎意味着它是同步运行的。我错过了什么吗?

public object GetItem()
{
     var task = GetItemAsync();
     var result = task.Result;

     return result
}
Run Code Online (Sandbox Code Playgroud)

Ole*_*egI 6

调用awaitable(返回的方法Task)方法的唯一正确方法就是await它。但你await只能在返回的方法内Task。在遗留代码中,您无法更改方法签名,因为您有太多引用,并且您基本上需要重构整个代码库。所以你有以下选择:

.Result
.Wait()
.GetAwaiter().GetResult()
Run Code Online (Sandbox Code Playgroud)

这些都不好。他们都会去block the thread。但是,如果您无法更改执行的方法签名await,我会选择最后一个选项 -GetAwaiter().GetResult()因为它不会将异常包装到AggregateException

  • 请参阅 https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.taskawaiter-1.getresult?view=netcore-2.2。微软警告不要使用最后一个选项,并表示它不适合在代码中使用。 (3认同)

Ian*_*ick 4

请参阅有关 Task<>.Result 的文档

System.Threading.Tasks.Task.Result 是一个阻塞调用,会等待任务完成。所以它本质上有一个内置的等待调用。

在该微软文档的备注部分:

访问属性的 get 访问器会阻塞调用线程,直到异步操作完成;相当于调用Wait方法。

不幸的是,微软没有在访问器的名称中反映这一点,因为这是该访问器的一个极其关键的副作用。