2013-03-19 32 views
5

Mi rendo conto che attendere attende per un'attività (attendibile) da completare. Ma sono confuso su cosa significhi in realtà.Async WebApi ActionFilterAttribute. Un modulo o gestore asincrono è stato completato mentre era ancora in attesa un'operazione asincrona

Il codice che non lo fa lavoro:

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

Il codice che fa lavoro:

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

Ovviamente il messaggio di errore Un modulo asincrono o gestore completato mentre un'operazione asincrona era ancora in sospeso. mi dice che non era in attesa che la chiamata asincrona si completasse, ma invece il thread "principale" continuava. Mi aspettavo che il thread continuasse ma non all'interno del metodo corrente. Pensavo che il thread sarebbe tornato nello stack di asp.net fare qualche altro lavoro e tornare una volta che l'operazione asyncOperation() è stata completata.

Sto usando attendere anche in altri luoghi - (ad esempio, in attesa di risposte al servizio Web) - e non ho riscontrato problemi simili ovunque. Mi chiedo perché IActionFilterAttribute si comporta in modo diverso. In effetti, le chiamate sul servizio web probabilmente richiedono più tempo rispetto alla lettura del contenuto della risposta in una stringa.

Qualcuno può per favore illuminarmi? Ho la sensazione di non aver capito il concetto.

+0

I filtri di azione (parte di MVC, non WebAPI) non supportano le operazioni asincrone. Se hai bisogno di un filtro di azione asincrono, prova invece a utilizzare un gestore di messaggi. Oh, e [vota qui] (http://aspnet.codeplex.com/workitem/9582). –

+0

Questa è una domanda WebAPI e sto usando il giusto ActionFilterAttribute (System.Web.Http ...) - stai dicendo che dovrebbe funzionare? :) – lapsus

+0

Capisco. In tal caso, sarà probabilmente necessario definire il proprio 'AsyncActionFilterAttribute' e implementare' IActionFilter.ExecuteActionFilterAsync'. –

risposta

6

L'aggiunta di codice asincrono a un metodo che restituisce il vuoto è pericolosa e quasi mai ciò che si desidera effettivamente fare. Vedi What's the difference between returning void and returning a Task?.

Invece, è necessario sovrascrivere/implementare un metodo che restituisce un'attività. In questo caso, ActionFilterAttribute nasconde l'attività fornita da IHttpActionFilter, pertanto è necessario implementare IActionFilter (ExecuteActionFilterAsync). Se vuoi usare il tuo codice come attributo, assicurati di derivare anche dalla classe Attribute.

Ad esempio:

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

Invece di implementare

public async override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 

è necessario implementare la versione asincrona di OnActionExecuted metodo come segue:

public override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) 

In questo modo è possibile utilizzare attendono all'interno di un metodo e il comportamento sarà come ti aspettavi.

Spero che questo aiuti.