- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有一个非常简单的 ASP.NET MVC 4 Controller :
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);
}
}
当我启动项目时,我看到了我的 View ,它看起来不错,但是当我更新页面时,我收到以下错误:
[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"; } );
它将正常工作。为什么不能在 Controller 的构造函数中使用 WebClient.DownloadStringTaskAsync
方法?
最佳答案
在Async Void, ASP.Net, and Count of Outstanding Operations , Stephan Cleary 解释了这个错误的根源:
Historically, ASP.NET has supported clean asynchronous operations since .NET 2.0 via the Event-based Asynchronous Pattern (EAP), in which asynchronous components notify the SynchronizationContext of their starting and completing.
发生的事情是您在类构造函数中触发 DownloadAsync
,在异步 http 调用中您在 await
中。这会向 ASP.NET SynchronizationContext
注册异步操作。当您的 HomeController
返回时,它发现它有一个尚未完成的挂起异步操作,这就是它引发异常的原因。
If we remove task = DownloadAsync(); from the constructor and put it into the Index method it will work fine without the errors.
正如我上面所解释的,那是因为从 Controller 返回时,您不再有挂起的异步操作在进行。
If we use another DownloadAsync() body return await
Task.Factory.StartNew(() => { Thread.Sleep(3000); return "Give me an
it will work properly.
error"; });
那是因为 Task.Factory.StartNew
在 ASP.NET 中做了一些危险的事情。它不使用 ASP.NET 注册任务执行。这可能会导致执行池回收的边缘情况,完全忽略您的后台任务,从而导致异常中止。这就是为什么你必须使用一种机制来注册任务,例如 HostingEnvironment.QueueBackgroundWorkItem
.
这就是为什么不可能按照您的方式做您正在做的事情。如果您真的希望它在后台线程中以“即发即弃”的方式执行,请使用 HostingEnvironment
(如果您使用的是 .NET 4.5.2)或 BackgroundTaskManager
.请注意,通过执行此操作,您将使用线程池线程来执行异步 IO 操作,这是多余的,并且正是使用 async-await
的异步 IO 试图克服的问题。
关于c# - ASP.NET Controller : An asynchronous module or handler completed while an asynchronous operation was still pending,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28805796/
我是一名优秀的程序员,十分优秀!