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

时间:2013-09-03 15:17:02

标签: c# async-await

这有点长啰嗦,但是这里...... [/ p>

鉴于我有这样的界面:

public interface IWebClientHelper
{
    TPayload Get<TPayload>(string url);
}

Get的实现调用提供的URL,该URL将返回包含类型为TPayload的Json对象的响应,并且Json被反序列化为TPayload并且然后回来了。

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

Task<TPayload> Get<TPayload>(string url);

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

public interface IAsyncWebClientHelper
{
    Task<TPayload> Get<TPayload>(string url);
}

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

public TPayload Get<TPayload>(string url)
{
    return _asyncWebClientHelper.Get<TPayload>(url).Result;
}

Get _asyncWebClientHelper方法包含

message = await httpClient.GetAsync(url);

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

1 个答案:

答案 0 :(得分:19)

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

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