异步HttpModule MVC

Jam*_*uth 6 asp.net-mvc httpmodule async-await

我有一个包含以下代码的同步HttpModule.

    /// <summary>
    /// Occurs as the first event in the HTTP pipeline chain of execution 
    /// when ASP.NET responds to a request.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">An <see cref="T:System.EventArgs">EventArgs</see> that 
    /// contains the event data.</param>
    private async void ContextBeginRequest(object sender, EventArgs e)
    {
        HttpContext context = ((HttpApplication)sender).Context;
        await this.ProcessImageAsync(context);
    }
Run Code Online (Sandbox Code Playgroud)

当我尝试从空的MVC4应用程序(NET 4.5)运行该模块时,我收到以下错误.

此时无法启动异步操作.异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动.如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async ="true"%>.

我似乎错过了一些东西但是通过我的阅读,错误实际上不应该发生.

我有一个挖掘,但我似乎无法找到任何帮助,有没有人有任何想法?

Ste*_*ary 13

因此,您在同步HttpModule事件处理程序中具有异步代码,并且ASP.NET抛出异常,指示异步操作只能在异步处理程序/模块中启动.对我来说似乎很简单.

要解决此问题,您不应BeginRequest直接订阅; 相反,创建一个 - Task返回"处理程序",将其包装EventHandlerTaskAsyncHelper,然后传递给它AddOnBeginRequestAsync.

像这样的东西:

private async Task ContextBeginRequest(object sender, EventArgs e)
{
  HttpContext context = ((HttpApplication)sender).Context;
  await ProcessImageAsync(context);

  // Side note; if all you're doing is awaiting a single task at the end of an async method,
  //  then you can just remove the "async" and replace "await" with "return".
}
Run Code Online (Sandbox Code Playgroud)

并订阅:

var wrapper = new EventHandlerTaskAsyncHelper(ContextBeginRequest);
application.AddOnBeginRequestAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler);
Run Code Online (Sandbox Code Playgroud)

  • 啊,不幸的是,`Microsoft.Bcl.Async`有[ASP.NET 4.0上的未定义行为](http://blogs.msdn.com/b/webdev/archive/2012/11/19/all-about-httpruntime- targetframework.aspx).在ASP.NET上,您*必须*在.NET 4.5上运行,而不是在.NET 4.0上运行. (2认同)