2013-03-19 2 views
5

Я понимаю, жду ждет для выполнения задачи (ожидаемой). Но я смущен тем, что на самом деле означает.Async WebApi ActionFilterAttribute. Асинхронный модуль или обработчик завершен, пока асинхронная операция все еще находится на рассмотрении

Код, который не работы:

public async override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 
{ 
    if (actionExecutedContext.Response.Content != null) 
    { 
     var responseContent = await actionExecutedContext.Response.Content.ReadAsStringAsync(); 
     DoSomething(responseContent); 
    } 
} 

Код, который делает работы:

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 
{ 
    if (actionExecutedContext.Response.Content != null) 
    { 
     var responseContent = actionExecutedContext.Response.Content.ReadAsStringAsync().ContinueWith(
     task => 
     { 
      DoSomething(task.Result); 
     }); 
    } 
} 

Очевидно, что сообщение об ошибке Асинхронный модуль или обработчик завершения время асинхронная операция продолжалась. говорит мне, что не было ожиданий завершения асинхронного вызова, но вместо этого продолжался «основной» поток. Я ожидал продолжения потока, но не в текущем методе. Я думал, что поток вернется в стек asp.net, выполнит какую-то другую работу и вернется после завершения операции asyncOperation().

Я также использую ожидание в других местах (например, ожидая ответов на веб-службу) - и я не сталкивался с подобными проблемами в любом месте. Интересно, почему IActionFilterAttribute ведет себя по-другому. На самом деле мои вызовы веб-службы, вероятно, занимают больше времени, чем чтение содержимого ответа в строку.

Может кто-нибудь, пожалуйста, просветит меня? У меня такое чувство, что я не понял эту концепцию.

+0

Фильтры действий (часть MVC, а не WebAPI) не поддерживают асинхронные операции. Если вам нужен фильтр асинхронных действий, попробуйте вместо этого использовать обработчик сообщений. О, и [проголосовать здесь] (http://aspnet.codeplex.com/workitem/9582). –

+0

Это вопрос WebAPI, и я использую правильный ActionFilterAttribute (System.Web.Http ...) - вы говорите, что он должен работать? :) – lapsus

+0

Я вижу. В этом случае вам, вероятно, потребуется определить свой собственный «AsyncActionFilterAttribute» и реализовать «IActionFilter.ExecuteActionFilterAsync». –

ответ

6

Добавление асинхронного кода в метод, возвращающий void, опасно и почти никогда не является тем, что вы на самом деле хотите сделать. См. What's the difference between returning void and returning a Task?.

Вместо этого вам необходимо переопределить/реализовать метод, возвращающий задачу. В этом случае ActionFilterAttribute скрывает задачу, которую предоставляет IHttpActionFilter, поэтому вам нужно будет реализовать IActionFilter (ExecuteActionFilterAsync). Если вы хотите использовать код в качестве атрибута, просто убедитесь, что вы также вышли из класса Attribute.

Например:

public class AsyncActionFilterAttribute : Attribute, IActionFilter 
{ 
    public async Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) 
    { 
     HttpResponseMessage response = await continuation(); 
     DoSomething(response); 
     return response; 
    } 
} 
0

Вместо реализации

public async override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 

вы должны реализовать вариант асинхронной из OnActionExecuted метода следующим образом:

public override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) 

Таким образом, вы можете использовать ждать внутри метода и поведения будет, как вы ожидали.

Надеюсь, это поможет.

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

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