Saturday, 19 December 2015

await VS Wait() when Task throws exception

await and Wait() are two versions of the operation "wait for the task to complete": one is asynchronous (non-blocking) and the other one is synchronous (blocking). They are both capable of capturing the exception thrown from the task but they behave in a different way when propagating exception information up the stack: they themselves throw different type of exception.


await (case 1) propagates the original exception so the output is:


System.ArgumentNullException: Value cannot be null.
   at Program.<>c.b__1_0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Program.d__1.MoveNext()
Task.Status: Faulted
Task.IsFaulted: True
Task.Exception: System.AggregateException: One or more errors occurred. ---> System.ArgumentNullException: Value cannot be null.
   at Program.<>c.b__1_0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Program.d__1.MoveNext()
   --- End of inner exception stack trace ---
---> (Inner Exception #0) System.ArgumentNullException: Value cannot be null.
   at Program.<>c.b__1_0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Program.d__1.MoveNext()<---


Wait() (case 2) wraps original exception in System.AggregateException:


System.AggregateException: One or more errors occurred. ---> System.ArgumentNullException: Value cannot be null.
   at Program.<>c.b__1_0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at Program.d__1.MoveNext()
---> (Inner Exception #0) System.ArgumentNullException: Value cannot be null.
   at Program.<>c.b__1_0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()<---

Task.Status: Faulted
Task.IsFaulted: True
Task.Exception: System.AggregateException: One or more errors occurred. ---> System.ArgumentNullException: Value cannot be null.
   at Program.<>c.b__1_0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
   --- End of inner exception stack trace ---
---> (Inner Exception #0) System.ArgumentNullException: Value cannot be null.
   at Program.<>c.b__1_0()
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()<---


Note that Task.Exception in both cases holds System.AggregateException. This difference comes from the desire of async-await implementers to keep use of await as simple as possible and to make its use to look like synchronous code as much as possible. System.AggregateException is not used in synchronous code (in non-TPL code) and we there always catch the first exception that is thrown from a try-block. That is why await is designed in such way so it throws only the first exception from a task (or aggregate of tasks) as usually we are interested only in that first exception (we usually handle the first error that occurs).

1 comment:

micheal pan said...

BE SMART AND BECOME RICH IN LESS THAN 3DAYS....It all depends on how fast 
you can be to get the new PROGRAMMED blank ATM card that is capable of
hacking into any ATM machine,anywhere in the world. I got to know about 
this BLANK ATM CARD when I was searching for job online about a month 
ago..It has really changed my life for good and now I can say I'm rich and 
I can never be poor again. The least money I get in a day with it is about 
$50,000.(fifty thousand USD) Every now and then I keeping pumping money 
into my account. Though is illegal,there is no risk of being caught 
,because it has been programmed in such a way that it is not traceable,it 
also has a technique that makes it impossible for the CCTVs to detect 
you..For details on how to get yours today, email the hackers on : (
atmmachinehackers1@gmail.com ). Tell your 
loved once too, and start to live large. That's the simple testimony of how 
my life changed for good...Love you all ...the email address again is ;
atmmachinehackers1@gmail.com