Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nesting async/await methods

I'm writing a library that wraps a third party web service call and am trying to make the library use the new async/await features. What is the proper use of the async/await keywords in the following example?

public class MyApi
{
    public Task<ApiResult> DoSomethingAsync()
    {
        return this.DoSomethingCore();
    }

    public async Task<ApiResult> DoSomethingElseAsync()
    {
        return await this.DoSomethingCore();
    }

    private async Task<ApiResult> DoSomethingCore()
    {
        var httpClient = new HttpClient();
        var httpResponseMessage = await httpClient.GetAsync("some url");
        var rawResultText = await httpResponseMessage.Content.ReadAsStringAsync();
        return new ApiResult(rawResultText);        
    }
}

To allow my caller to await the DoSomethingAsync method, should that method also have the async and await keywords added to it? Or is it fine as-is because it returns a Task? Is there a better pattern for this sort of nesting?

I think the DoSomethingAsync method is the correct way to go here, is that correct? I believe DoSomethingElseAsync seems the wrong approach when building a library.

like image 887
Brian Vallelunga Avatar asked Aug 02 '12 14:08

Brian Vallelunga


People also ask

Can I nest async functions?

async functions returning promises is a good thing because you can nest async functions.

Can one async function have multiple awaits?

In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise. all() . Promise. all() will wait for all the provided async calls to be resolved before it carries on(see Conclusion for caveat).

Does async await use thread pool?

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active.

What happens if an async method is not awaited?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.


2 Answers

Any Task can be awaited, regardless of where it came from.

I'm not sure why DoSomethingAsync just calls DoSomethingCore, since DoSomethingAsync could just as easily be async and use await.

There is also a general rule that you should use ConfigureAwait(false) in library methods.

Edit: If you don't need to use await, then don't make the method async. async will add some overhead (check Channel9 for Stephen Toub's Zen of Async Performance video). If you can just return a Task (like DoSomethingAsync), then do it that way.

like image 102
Stephen Cleary Avatar answered Sep 21 '22 12:09

Stephen Cleary


The formulation below is functional, but will likely cause additional overhead (due to having a secondary callback for the additional async/await method.)

public async Task<ApiResult> DoSomethingElseAsync()
{
    return await this.DoSomethingCore();
}

It's simpler to return the Task directly, as you can always await that Task elsewhere without having to have the method implemented as 'async'. Async/await is a lot like using 'yield return'; it does some compiler magic to implement the 'yielding', but the enumeration itself doesn't care how you implement it. Likewise, an 'await' call doesn't care how the awaitable works, as long as it's awaitable.

like image 32
Dan Bryant Avatar answered Sep 20 '22 12:09

Dan Bryant