9 votes

ASP.NET 4.5 async-await et Response.Redirect

Y a-t-il un moyen de rediriger de Page_Load (ou tout autre événement ASP.NET) lors de l'utilisation de la fonction async - await ? Bien sûr. Redirect jette ThreadAbortException mais même si je l'attrape avec try - catch une page d'erreur s'affiche. Si j'appelle Response("url", false) il ne se plante pas mais je dois arrêter l'exécution de la page (rendu de la page etc.) donc ce n'est pas la solution. Et comme je l'ai remarqué, ces deux méthodes agissent différemment :

Cela aboutit à une ThreadAbortException (je suppose que la tâche se termine de manière synchrone) :

protected async void Page_Load()
{
    await Task.Run(() => { });
    Response.Redirect("http://www.google.com/");
}

Celui-ci continue après Response.Redirect :

protected async void Page_Load()
{
    await Task.Delay(1000);
    Response.Redirect("http://www.google.com/");
}

Je dois attendre la réponse mais j'étais en train d'expérimenter et même si j'enlève le await (pour que la tâche s'exécute en arrière-plan et que la méthode continue), le résultat est le même. La seule chose qui aide est de supprimer le mot-clé async mot-clé - je pensais async Permet SEULEMENT await et rien de plus !

2voto

JakubRi Points 181

OK, j'ai trouvé la réponse à cette question.

J'ai créé un wrapper de la méthode Redirect dans ma classe de base Page :

protected void Redirect(string url)
{
    this.isRedirecting = true;

    Response.Redirect(url, false);

    if (Context.ApplicationInstance != null)
        Context.ApplicationInstance.CompleteRequest();
}

Et passer outre Render y RaisePostBackEvent :

protected override void Render(HtmlTextWriter writer)
{
    if (this.isRedirecting)
        return;
}

protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
{
    if (!this.isRedirecting)
        base.RaisePostBackEvent(sourceControl, eventArgument);
}

Cela fait l'affaire. ASP.NET 4.5 ne déclenchera pas la fonction PreRenderComplete (= ne continuera pas dans le cycle de vie) jusqu'à ce que toutes les tâches attendues soient terminées.

1voto

Chris Points 15358

Diclaimer : Je n'ai pas utilisé async / await mais ce qui suit est basé sur ma lecture de la documentation.

Si je comprends bien, chaque fois que vous avez un await dans le code, il appellera la tâche fournie de manière aynchrone et le reste de la méthode est en fait converti en une méthode de rappel. Ainsi, dans ce cas, parce que Page_Load est asynchrone lorsqu'il est exécuté et qu'il arrive à un await, il rendra le contrôle à l'appelant en attendant que sa tâche aynchrone soit terminée.

Dans le cas de la Page_Load Le cycle de vie de la page se poursuivra probablement jusqu'à l'étape suivante.

Ces différences s'expliquent par le fait que, dans votre premier exemple, bien que le cycle de vie se poursuive, le rappel est presque immédiat, de sorte que l'option Response.Redirect s'exécutera presque immédiatement, avant que le reste de la page ait la possibilité de faire quoi que ce soit.

Dans le cas de la seconde, vous avez un délai de 1000 et pendant ce temps, la page continue à exécuter d'autres choses et ce n'est que lorsque ce délai est écoulé que la redirection respone.redirect se déclenche. Cela peut être après qu'une réponse (d'une erreur) ait déjà été envoyée.

Donc, en substance async permet await mais quoi await On dirait que c'est un peu plus que ce à quoi vous vous attendez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X