等待Task.Result如何影响嵌套的async/await方法?

Chr*_*yne 5 c# async-await

这有点长啰嗦,但这里......

鉴于我有这样的界面:

public interface IWebClientHelper
{
    TPayload Get<TPayload>(string url);
}
Run Code Online (Sandbox Code Playgroud)

其中实现Get调用提供的URL,它将返回包含类型的Json对象的响应TPayload,并将Json反序列化为TPayload然后返回.

我想使Get方法的实现异步(或者更具体地说,使Get方法中包含的HTTP调用异步),但据我所知,这将要求将Get方法的签名更改为:

Task<TPayload> Get<TPayload>(string url);
Run Code Online (Sandbox Code Playgroud)

我的目标是保持接口不变,所以我创建了第二个接口:

public interface IAsyncWebClientHelper
{
    Task<TPayload> Get<TPayload>(string url);
}
Run Code Online (Sandbox Code Playgroud)

并将其注入我的实现中IWebClientHelper.所以现在我的实现IWebClientHelper看起来像这样:

public TPayload Get<TPayload>(string url)
{
    return _asyncWebClientHelper.Get<TPayload>(url).Result;
}
Run Code Online (Sandbox Code Playgroud)

以及包含该行的Get方法_asyncWebClientHelper

message = await httpClient.GetAsync(url);
Run Code Online (Sandbox Code Playgroud)

所以我不清楚的是:我是否认为该行将return _asyncWebClientHelper.Get<TPayload>(url).Result阻止执行直到该方法返回?或者await该方法中的关键字是否会释放该线程,直到它收到来自网址的响应?

Jon*_*eet 19

是的,使用Result意味着您的方法将阻止.但是,这很可能意味着它实际上会导致死锁.你还没有告诉我们很多关于上下文的信息,但是如果你处于一个上下文中,await你需要返回到同一个线程,但是该线程被阻塞了Result,你基本上就会陷入僵局.在使用任何阻塞调用(例如属性或方法)时,您需要非常小心.ResultWait()

从根本上说,尝试在不使接口异步的情况下使用异步是棘手/无意义的.你可以更好地全心全意地拥抱异步,或者坚持使用同步版本.毕竟,如果您要在异步任务完成之前保持线程被阻塞,那么异步的优势首先在于什么?