akhileshcoer akhileshcoer - 2 months ago 27
C# Question

Nested Async calls with Top level function doing await

I've this scenario, wanted to check if is feasible before going that route.

I've a webApi project, there is a delegateHandler which adds some data in HttpContext.Current.Items. In controller there are few async calls which I'm doing with configureawait(false). Same in the library DLL.

Overall code looks like this.....

In controller

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
}


In DLL, class DBCalls

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


Question is when execution resumes back on controller function will I get stored data back from HttpContext.Current.Items?

Answer

When execution resumes back on controller function will I get stored data back from HttpContext.Current.Items?

No, you won't. ConfigureAwait(false) is exactly for the case when you don't need to resume on the previous context. But to access HttpContext.Current, you need that.

What you should do is to use ConfigureAwait(false) in "library" code (like InternalMethodN and possibly Method1Async), which does not depend on the context. But in your "application" code, which needs to return to the ASP.NET request context, don't use ConfigureAwait().

So, your code should look like this:

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

Note that I have changed MethodNAsync from async void to async Task. You shouldn't use async void methods unless you have to and you certainly wouldn't be able to await them.

Also, I'm assuming that the real MethodNAsync actually do something. If they just delegate to the internal methods, you could simplify them to just (using C# 6.0 expression-bodied methods to make them even shorter):

Task Method1Async() => InternalMethod1();

Task Method2Async() => InternalMethod2();