嵌套Async调用,顶级函数执行await

本文关键字:函数 执行 await Async 调用 嵌套 | 更新日期: 2023-09-27 18:07:13

我有这样一个场景,想在走那条路之前检查一下是否可行。

我有一个webApi项目,有一个delegateHandler在HttpContext.Current.Items中添加一些数据。在控制器中,我正在使用configureawait(false)进行一些异步调用。在库DLL中也是如此。

总体代码如下.....

在控制器

public async Task<Entity> func()
{
HttpContext.Current.Items.Add(key, value);
await DBCalls.Method1Async().configureawait(false);
await DBCalls.Method2Async().configureawait(false);
var data = HttpContext.Current.Items[key];
// rest of the method
}

DLL中,DBCalls类

async void Method1Async()
{
   await internalMethod1().configureawait(false)
}
async void Method2Async()
{
   await internalMethod2().configureawait(false)
}

问题是,当执行恢复回到控制器功能,我会得到存储的数据从HttpContext.Current.Items回来吗?

嵌套Async调用,顶级函数执行await

当控制器函数恢复执行时,我将从HttpContext.Current.Items获得存储的数据吗?

不,你不会。当不需要恢复上一个上下文时,ConfigureAwait(false)正好适用于这种情况。但是要访问HttpContext.Current,你需要这个

您应该做的是在"库"代码(如InternalMethodN和可能的Method1Async)中使用ConfigureAwait(false),这不依赖于上下文。但是在您的"应用程序"代码中,需要返回到ASP。. NET请求上下文,不要使用ConfigureAwait() .

所以,你的代码应该是这样的:
public async Task<Entity> Func()
{
    HttpContext.Current.Items.Add(key, value);
    await DBCalls.Method1Async();
    await DBCalls.Method2Async();
    var data = HttpContext.Current.Items[key];
    // rest of the method
}
async Task Method1Async()
{
   await InternalMethod1().ConfigureAwait(false);
}
async Task Method2Async()
{
   await InternalMethod2().ConfigureAwait(false);
}

请注意,我已将MethodNAsyncasync void更改为async Task。除非迫不得已,否则你不应该使用async void方法,而且你肯定不能使用await方法。

另外,我假设真正的MethodNAsync实际上做了一些事情。如果它们只是委托给内部方法,您可以将它们简化为(使用c# 6.0表达式体方法使它们更短):

Task Method1Async() => InternalMethod1();
Task Method2Async() => InternalMethod2();