我仍在了解.NET 4.5的各种异步特性,我遇到了一些有趣的事情。在我的MVC控制器中,执行(1)和(2)时会得到不同的结果。
public ActionResult Index() {
var stuff = SomeExpensiveFunction();
return View(stuff);
}
private byte[] SomeExpensiveFunction() {
string url = "http://some-url.../";
// (1)
var wc = new WebClient();
return wc.DownloadDataTaskAsync(url).Result;
// (2)
var hc = new HttpClient();
return hc.GetAsync(url).Result.Content.ReadAsByteArrayAsync().Result;
}
表面上看起来,它们似乎是相同的 -
WebClient.DownloadDataTaskAsync
和 HttpClient.GetAsync
都是返回 Task
的 async
方法。其中,WebClient
版本返回 Task<byte[]>
,而 HttpClient
版本返回 Task<HttpResponseMessage>
,我需要从中挖掘出字节,但无论哪种方式,我都调用了 .Result
,我希望在离开函数之前完成。
对于(1),我会得到一个带有 An asynchronous operation cannot be started at this time...
的黄屏错误。对于(2),一切正常。
我可以改变整个堆栈,并在控制器方法自身和 SomeExpensiveFunction
上使用 async
,然后一切正常。但我试图弄清楚是否存在与(1)或使用 MVC 时与 WebClient
总体上存在一些根本性问题。您有什么想法吗?
编辑:我知道在这个例子中,我可以使用这些调用的同步版本,因为我并没有真正地异步执行任何操作 - 这只是基于更大的代码库的一个例子。
HttpClient
做完全相同的事情却没有错误。也许WebClient
和HttpClient
在内部异步处理方面有所不同,即使最终它们都返回一个Task<>
。 - Joe Enos