Reputation: 174
I have issues understanding a detail about async programming in C#.
Lets say I have a common async method, that has a few await statements in it. Lets say I have another method, which is not async, but calls the first method.
public void DoSomething(){
DoSomethingAsync()
...
}
public async Task DoSomethingAsync(){
...
await ...
...
}
I know i could just use Wait()
or some other synchronization technique, but i dont just want to throw stuff at problems without knowing what happens.
Will DoSomething
continue execution before DoSomethingAsync
is completed? I know that this would happen if DoSomething
were to be declared async
, but it isn't.
Or to be more general: Can synchronous methods continue their execution before an asynchronous sub-call has completed?
Upvotes: 0
Views: 723
Reputation: 457147
Can synchronous methods continue their execution before an asynchronous sub-call has completed?
As others have noted, the answer to this is "yes".
All asynchronous methods begin executing synchronously. They return a task that represents the completion of that asynchronous method. The task is completed when the asynchronous method is completed. If the asynchronous method returns a result, then the task is completed with a result value. If the asynchronous method throws an exception, then the task is completed with an exception (i.e., faulted).
However, this also means that there is are some problems with the code you've posted. Specifically, it's doing a kind of "fire and forget", and that's dangerous.
This code is just ignoring the task returned from DoSomethingAsync
:
public void DoSomethingElse(){
DoSomethingAsync()
...
}
So that means it's saying "start doing something" and it's also saying "I don't care if or when that 'something' completes, and I don't care if it throws an exception". There are a couple problems with this: 1) since your app doesn't know when "something" completes, it can't know when it's safe to shut down, and 2) your app won't be notified if "something" fails.
In the vast, vast majority of scenarios, that means the app has bugs. "Fire and forget" is only appropriate when doing an operation where it doesn't actually matter if the operation fails or isn't even completed. There are very few operations where this is the case.
This is why - as a general rule - tasks should eventually be await
ed. If you want to start an operation and then do other things and then await
that operation to complete, that's not uncommon:
public async Task DoSomethingElseAsync() {
var task = DoSomethingAsync();
... // other synchronous/asynchronous work.
await task; // asynchronously wait for DoSomethingAsync to complete,
// and propagate any exceptions.
}
Upvotes: 1
Reputation: 1308
TL;DR It continues
Can synchronous methods continue their execution before an asynchronous sub-call has completed?
Of course it can, if a synchronous method has to wait an asynchronous method to finish, what's the purpose of going asynchronous? (It can wait as well, depending on what you want to achieve)
async/await
pattern in your code will create a state machine that can be recovered later. By the time your code hits await
, the task you await
on will be pushed to the task scheduler and might be executed in some threadpool thread. The async
method returns and let the synchronous method continue.
When the task is finished, the state machine recovers the context, and everything in DoSomethingAsync
after await
continues. On which thread it would run? This depends on if you set ConfigureAwait and the threading model of your program. For example, for a WPF application, by default, it comes back to the main thread, and that's why wait
+ await
can lead to deadlocks.
Upvotes: 1
Reputation: 7595
In the absence of the await operator this method will behave as if this call is not awaited, execution of the current method continues before the call is completed
The compiler will warn you:
Upvotes: 1
Reputation: 906
What happens is:
DoSomething
calls DoSomethingAsync
.
Then a synchronous! order starts until the first "await" is reached.
With this await, the DoSomethingAsync
returns a Task object the has status "not finished yet". But as you do not assign this return value and also do nothing else special your DoSomething
continues.
Upvotes: 1