我仍在了解 .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
都是async
返回 a 的方法Task
。WebClient
版本返回Task<byte[]>
,而版本HttpClient
返回Task<HttpResponseMessage>
,我必须从中挖掘字节,但我正在调用.Result
任何一种方式,我希望在离开函数之前完成。
使用 (1),我得到一个带有An asynchronous operation cannot be started at this time...
. 使用(2),一切正常。
我可以更改整个堆栈并async
在控制器方法本身和 上使用SomeExpensiveFunction
,一切正常。但是我试图弄清楚WebClient
在使用 MVC 时 (1) 或一般情况下是否存在根本性问题。有什么想法吗?
编辑:我知道在这个例子中我可以使用这些调用的同步版本,因为我并没有真正异步地做任何事情——这只是一个基于更大代码库的例子。