我有一个非常简单的ASP.NET MVC 4控制器的异步模块或处理程序:ASP.NET控制器:完成,而异步操作仍然悬而未决
public class HomeController : Controller
{
private const string MY_URL = "http://smthing";
private readonly Task<string> task;
public HomeController() { task = DownloadAsync(); }
public ActionResult Index() { return View(); }
private async Task<string> DownloadAsync()
{
using (WebClient myWebClient = new WebClient())
return await myWebClient.DownloadStringTaskAsync(MY_URL)
.ConfigureAwait(false);
}
}
当我开始的项目,我看到我的观点和它看起来不错,但当我更新页面时,出现以下错误:
[InvalidOperationException: An asynchronous module or handler completed while an asynchronous operation was still pending.]
为什么会发生?我做了几个测试:
- 如果我们从构造函数中删除
task = DownloadAsync();
,并把它放入Index
方法它会正常工作没有错误。 - 如果我们使用另一个
DownloadAsync()
机身return await Task.Factory.StartNew(() => { Thread.Sleep(3000); return "Give me an error"; });
它会正常工作。
为什么无法在控制器的构造函数中使用WebClient.DownloadStringTaskAsync
方法?
感谢您的回答。我已经阅读过你提到的那篇文章,但我再读一遍。我不知道为什么我以前没有意识到它,但我的问题的关键应该是第二句话:“MVC框架了解如何等待您的”任务“,但它甚至不知道'async void',所以它向ASP.NET内核返回完成,它看到它实际上并没有完成。“控制器的构造函数被编译成'void'方法,这就是为什么我得到错误。我对吗? – dyatchenko 2015-03-02 10:04:36
@dyatchenko号。这与'async void'无关。 ASP.NET知道如何处理'async Task'。因为它注册到'SynchronizationContext',它注意到你的'DownloadAsync'方法在你的控制器返回时没有完成。 – 2015-03-02 10:05:55
好的。在这种情况下,正如你所提到的,我可以等几秒钟,而我的下载完成后,我可以刷新页面,它应该没问题,但事实并非如此。 – dyatchenko 2015-03-02 10:14:49