2013-07-25 2 views
5

У меня есть синхронный HttpModule, содержащий следующий код. Асинхронный HttpModule MVC

/// <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); 
    } 

Когда я пытаюсь запустить модуль из пустого приложения MVC4 (NET 4.5) я получаю следующее сообщение об ошибке.

Асинхронная операция не может быть запущена в это время. Асинхронные операции могут запускаться только в асинхронном обработчике или или в течение определенных событий в жизненном цикле страницы. Если это исключение произошло при выполнении страницы, убедитесь, что страница отмечена <% @ Page Async = "true"%>.

Мне не хватает чего-то, но, по моему мнению, ошибка на самом деле не возникает.

У меня есть копать, но я не могу найти ничего, чтобы помочь, есть ли у кого-нибудь идеи?

ответ

10

Итак, у вас есть асинхронный код в синхронном обработчике событий 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". 
} 

и подписаться:

var wrapper = new EventHandlerTaskAsyncHelper(ContextBeginRequest); 
application.AddOnBeginRequestAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler); 
+0

Это должно быть в несколько раз вы помогли мне сейчас, спасибо! Я бы сказал, извините, код действительно написан в Net 4.0 и использует библиотеки BCL для поддержки ключевого слова async, чтобы я мог поддерживать как 4.0, так и 4.5. Поскольку такой EventHandlerTaskAsyncHelper недоступен для меня. –

+2

А, к сожалению, '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. –

+0

Ah ok ... Итак, проверяя это, если я удаляю 'targetFramework =" 4.5 "' из узла '' в web.config, это работает. Означает ли это, что в NET 4.0 мой httpModule не является, по сути, асинхронным? Это также означает, что я не могу использовать асинхронный httpModule без «EventHandlerTaskAsyncHelper» с MVC или есть другой способ. Я все еще смущен, что это ошибка, если честно. Сообщение, кажется, говорит, что httpModules в порядке. –

Смежные вопросы