I have a theoretical question to you. What happens if I await the Result of a Task inside another task? I want to know if my current system will work afterwards.
A task gets launched and does some stuff. At some point that task might need another one in order to process data which the current task is not able to process by itself. So I use await to ensure that the current task won't continue as long as he has not the result of the helper task. But what happens if the helper fails? Will the current task remain locked?
Can I avoid this deadlock somehow (without changing the system itself - task inside task)?
It's really easy to test. For example:
Both tests pass, notice that
Wait
throws anAggregateException
, andawait
throws theException
.You can only
await
aTask.Result
if it is anawaitable
(meaning it has aGetAwaiter
method). This is rarely the case. I assume you meanawait
on an inner Task.First, im not sure what you mean by "locked". The task isn't locked while you
await
on the inner task. Control is yielded back to the calling method until that inner task completes. If that inner task fails and you fail to properly handle that exception, you parent task will fault as well. You need to make sure you handle exceptions gracefully:If you
await
on the parent Task, you'll notice the inner exception propogating from the unhandled inner Task.I see no reason why your code should deadlock in this specific case. Not sure why this worries you.
The core idea behind
async
andawait
is that asynchronous code works just about the same as synchronous code.So, if you have synchronous code like this:
then you would expect
DoStuff
to propagate theInvalidOperationException
from the helper method. Similarly, that's what happens with asynchronous code:That is,
DoStuffAsync
will also propagate theInvalidOperationException
.Now, it doesn't work exactly the same way, of course, since it must be asynchronous, but the general idea is that all your control flow such as
try
/catch
,for
loops, etc, all "just work" for asynchronous code very similarly to synchronous code.What's actually going on is that when
HelperMethod
ends with anInvalidOperationException
, the exception is caught and placed on the returnedTask
, and the task is completed. When theawait
inDoStuffAsync
sees that the task has completed, it examines its exceptions and re-raises the first one (in this case, there is only one, theInvalidOperationException
). And it re-raises it in a way that preserves the call stack on the exception. This in turn causes theTask
returned fromDoStuffAsync
to be completed with that same exception.So, under the covers
async
andawait
are doing a bit of work to ensure that you can just call other methods withawait
and usetry
/catch
the same way as you would in synchronous code. But most of the time you don't have to be aware of that.