Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

does last async call in async method require await?

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.

like image 994
Alex Avatar asked Nov 29 '13 13:11

Alex


People also ask

Is await mandatory in async function?

An async function without an await expression will run synchronously. The await expression causes async function execution to pause until a Promise is settled (that is, fulfilled or rejected), and to resume execution of the async function after fulfillment.

Can you call an async method without await?

@PeterRitchie You can have a method that is functionally asynchronous, doesn't use the await keyword, and doesn't use the async keyword, but there is no point whatsoever in using the async keyword without also using await in the definition of that method.

Can we have a async function with and without await?

Async function without await inside We can declare a function as async without using any await . In this case, the execution is not paused and your code will be executed in a non-blocking manner (asynchronous - no waiting). It is the same as not declaring that same function with async .

Does a function calling an async function need to be async?

If you're writing an API and your function sometimes return promises it is best to make them always return promises - more generally if a function is sometimes asynchronous (with callbacks too) it should always be asynchronous. Yes, unless of course you're also doing other things inside the function.


1 Answers

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.

like image 101
Tim S. Avatar answered Nov 15 '22 05:11

Tim S.