在ASP.NET事件处理程序中使用async / await是否安全?

时间:2014-12-03 22:07:43

标签: c# asp.net webforms async-await

当我遇到这个时,我在ASP.NET中做了一些编码:

protected async void someButtonClickHandler(...)
{
    if(await blah)
        doSomething();
    else
        doSomethingElse();
}

在询问this问题后,我更了解async / await的工作原理。但是,让我感到震惊的是,按照上面显示的方式使用async / await是否安全? 我的意思是在调用await blah后调用者继续执行。这意味着它可能会在await blah完成之前将响应呈现给客户端。这是正确的吗?如果是doSomething() / doSomethingElse()会发生这种情况。他们会被处决吗?如果它们被执行了,用户是否会看到其变化的影响? 在我的情况下,这些方法会更改显示给用户的一些数据,但我也想知道在一般情况下会发生什么。

2 个答案:

答案 0 :(得分:20)

是的,这是安全的,但不是真的推荐。 recommended way to do this is via RegisterAsyncTaskMSDN article on async ASP.NET。但是,ASP.NET(Web窗体)将正确处理async void事件处理程序。

处理程序await时,响应不会呈现给客户端; await仅产生ASP.NET运行时,而不是客户端。 ASP.NET运行时知道事件处理程序尚未完成,因此它知道不发送响应。当事件处理程序完成时,ASP.NET运行时通过在那时发送响应来响应。

我有an earlier MSDN article您可能会觉得有帮助。如果您对ASP.NET运行时如何意识到async处理程序尚未完成感到好奇,我将在{{3}}中介绍它。

答案 1 :(得分:0)

我同意 Stephens 的回答(简而言之,ASP.NET SynchronisationContext 会持续监视正在运行的任务数),但因为它是(最好避免的)async void,您可能想要记录任何否则会被忽视的异常:

protected async void someButtonClickHandler(...)
{
    try{
        await someButtonClickHandlerInner(...)
    }
    catch (AggregateException ex)
    {
        logger.log(ex.flatten());
    }
    catch(Exception e){
        logger.log(e);  
    }
}

private async Task someButtonClickHandlerInner(...){
    if(await blah)
        doSomething();
    else
        doSomethingElse();
}