does last async call in async method require await?

.net, asynchronous, c#

Solution

In the following method:

public async Task CallAsync(byte[] data)
{
    await Call1Async(data);
    Call2Async(data);
}

Control from the method returns after beginning `Call2Async`. That is, if you were to `await CallAsync(data)`, it would finish before `Call2Async` ends. This is probably not what you intended. This method will only finish when both calls are complete:

public async Task CallAsync(byte[] data)
{
    await Call1Async(data);
    await Call2Async(data);
}

You can see the difference in these example outputs (I implemented the two async calls to simply print a start, delay for a second, and then print an end).

void Main()
{
    Console.WriteLine("Main start");
    CallAsync(null).Wait();
    Console.WriteLine("Main end");
}

The method without the second `await` prints:

Main start
Call1Async start
Call1Async end
Call2Async start
Main end
Call2Async end

And with the second `await`:

Main start
Call1Async start
Call1Async end
Call2Async start
Call2Async end
Main end

This implementation also has a problem:

public Task CallAsync(byte[] data)
{
    Call1Async(data);
    return Call2Async(data);
}

It kicks off both async calls at the same time, but then returns control when `Call2Async` completes, whether `Call1Async` is complete or not. Again, this is probably not what you intended.

Problem

I can't understand if await statement is required when async method call is the last call in my async method. E.g. ``` public async Task CallAsync(byte[] data) { await Call1Async(data); Call2Async(data); } public async Task Call1Async(byte[] data) { ... } public async Task Call2Async(byte[] data) { ... } ``` The above would compile but with a warning "consider applying await to this method". But I think it would be waste of resources to apply await for the last call in the method. At the same time, if I use `return Call2Async(data);` instead of just `Call2Async(data);`, the warning would go away. This indicates `await` is not actually required in such situation. But this only works for methods which have a return value (i.e. `Task<T>` rather than just `Task`). I need this for methods without return values. Is there any way to do the same for value-returning methods? I.e. I need to somehow return `Task` object returned by `Call2Async` to the caller of `CallAsync` and I can't use `return` statement in `CallAsync` explicitly as my methods don't have return values. Of course, I can adjust them all to return values (e.g. true) but it would not be an elegant solution. P.S. If I have the only async call in my method, I just don't add 'async' to the method signature, and it works ('return' statement not required). But if the method contains more than one async call, I need to have 'async' modifier to be able to await for the first call 'await Call1Async(data)'. And adding 'async' modifier makes the compiler require 'return' to return Task object to the caller (and this works only for methods with return values). That's what I'm trying to overcome.

Original source