ASP.NET 4.5 async-await和Response.Redirect

时间:2012-10-29 16:07:53

标签: asp.net .net redirect asynchronous async-await

使用Page_Load - async时,有没有办法从await(或任何其他ASP.NET事件)重定向?当然Redirect会引发ThreadAbortException,但即使我抓住try - catch,也会出现错误页面。如果我调用Response("url", false)它不会崩溃,但我需要停止执行页面(渲染页面等),所以这不是解决方案。正如我注意到这两种方法的行为不同:

这最终导致ThreadAbortException(我假设任务同步结束):

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

这个在Response.Redirect:

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

我必须等待响应,但我正在尝试,即使我删除了await关键字(因此任务在后台运行并且方法仍在继续),它最终也是如此。唯一有帮助的是删除async关键字 - 我认为async仅启用await而已启用?

2 个答案:

答案 0 :(得分:2)

好的,我找到了答案如何处理它。

我在我的基页类中创建了一个Redirect方法包装器:

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

    Response.Redirect(url, false);

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

并覆盖RenderRaisePostBackEvent

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

这就是诀窍。在完成所有等待的任务之前,ASP.NET 4.5不会触发PreRenderComplete事件(=将不会在生命周期中继续)。

答案 1 :(得分:1)

Diclaimer:我没有使用async / await,但以下内容是基于我对文档的阅读。

据我所知,只要代码中有await,它就会异步调用任务,其余方法实际上会转换为回调方法。因此,在这种情况下,因为Page_Load在运行它时是异步的并且它等待它将在等待其异步任务完成时将控制权返回给调用者。

Page_Load事件的情况下,我认为,这似乎已经完成,因为页面生命周期将继续下一步。

差异的原因在于,在您的第一个示例中,虽然它将继续生命周期,但回调几乎是立即的,因此Response.Redirect几乎会立即运行,然后页面的其余部分才有机会做任何事。

在第二个的情况下,你有1000的延迟,在此期间页面将继续运行其他事情,并且只有在延迟结束时respone.redirect才会触发。这可能是在已经触发了响应(来自错误)之后。

所以实质上async会启用await,但await听起来比你期望的要多一些。