简体   繁体   English

从同步方法调用异步方法

[英]Calling Async Method from Sync Method

I see a lot of questions about calling asyc methods from sync ones, like here: How to call asynchronous method from synchronous method in C#?我看到很多关于从同步方法调用异步方法的问题,例如: How to call asynchronous method from synchronous method in C#?

I understand the solutions however, experimentally, I am seeing that I don't need to add a .Wait() or Task.Run(async () => await MyAsyncMethod()) for it to run synchronously.我理解解决方案,但是,通过实验,我发现我不需要添加Task.Run(async () => await MyAsyncMethod()) .Wait()Task.Run(async () => await MyAsyncMethod())让它同步运行。 I have a get method that pulls information from a DB.我有一个从数据库中提取信息的 get 方法。

My code is below and when I run, it waits at var task = GetItemAsync() and I get the correct result from the DB.我的代码在下面,当我运行时,它等待var task = GetItemAsync()并且我从数据库中获得正确的结果。 I find it hard to believe that the DB call could come back before the code would move on which seems to imply that it ran synchronously.我发现很难相信 DB 调用会在代码继续运行之前返回,这似乎意味着它是同步运行的。 Am I missing something?我错过了什么吗?

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

     return result
}

See The docs on Task<>.Result请参阅Task<>.Result 上的文档

System.Threading.Tasks.Task.Result is a blocking call that waits until the task finishes. System.Threading.Tasks.Task.Result 是等待任务完成的阻塞调用。 So it has a built in wait call essentially.所以它本质上有一个内置的等待调用。

In the remarks section of that microsoft doc:在该微软文档的备注部分:

Accessing the property's get accessor blocks the calling thread until the asynchronous operation is complete;访问属性的 get 访问器会阻塞调用线程,直到异步操作完成; it is equivalent to calling the Wait method.相当于调用了Wait方法。

It's unfortunate that Microsoft did not reflect this in the name of the accessor because it's an extremely critical side effect of this accessor.遗憾的是,微软并没有在访问器的名称中体现这一点,因为这是访问器的一个极其关键的副作用。

The only right way to call awaitable(method which returns Task ) method is to await it.调用 awaitable(method which returns Task ) 方法的唯一正确方法是await它。 But you can await only within the method which returns Task .但是您只能在返回Task的方法中await In legacy code it happens you cannot change the method signature because you have too many reference and you need to basically refactor entire code base.在遗留代码中,您无法更改方法签名,因为您有太多引用,并且基本上需要重构整个代码库。 So you have these options:所以你有这些选择:

.Result
.Wait()
.GetAwaiter().GetResult()

Neither of those are good.这两个都不好。 All of them are going to block the thread .所有这些都会block the thread But if you cannot change the method signature to await the execution, I would pick the last option - GetAwaiter().GetResult() becasue it will not wrap the exception into AggregateException但是,如果您无法更改方法签名以await执行,我会选择最后一个选项 - GetAwaiter().GetResult()因为它不会将异常包装到AggregateException

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

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