Tuesday, 15 September 2015

c# - Why is TaskCanceledException thrown and does not always breaks into the debugger -



c# - Why is TaskCanceledException thrown and does not always breaks into the debugger -

i'm digging async-await mechanism , observed throwing of taskcanceledexception can't explain yet.

in sample below (self contained) have statement

await task.run(() => null);

i know statement on useless isolated issue, real code has logic , returns null in cases.

why throw taskcanceledexception? if homecoming arbitrary number (5 in below example) not throw.

furthermore if await method debugger of vs breaks if don't await message written output window of vs.

internal class programme { private static void main(string[] args) { var testasync = new testasync(); // exception thrown debugger not step in. message logged output window testasync.testasyncexceptiononlyintheoutputwindow(); // exception thrown , debugger breaks testasync.testasyncexceptionbreaksintothedebugger(); console.readkey(); } } internal class testasync { public async void testasyncexceptiononlyintheoutputwindow() { testnullcase(); } public async void testasyncexceptionbreaksintothedebugger() { await testnullcase(); } private static async task testnullcase() { // not throw taskcanceledexception await task.run(() => 5); // throw taskcanceledexception await task.run(() => null); } }

taskcanceledexception

the reason task.run(() => null) returns canceled task rests in overload resolution. compiler chooses static task run(func<task> function) , not static task<tresult> run<tresult>(func<tresult> function) 1 may expect. acts if you're calling async delegate, in case you're not. results in task.run "unwrapping" homecoming value (null) task in turn cancel task.

the specific code responsible in processinnertask private method in unwrappromise<tresult> (inherits task<tresult>) class:

private void processinnertask(task task) { // if inner task null, proxy should canceled. if (task == null) { trysetcanceled(default(cancellationtoken)); _state = state_done; // ... , record done } // ... }

you can tell compiler not telling compiler not returning task:

var result = await task.run(() => (object)null); // not throw exception. result null exception handling

the difference between 2 methods in testasyncexceptiononlyintheoutputwindow don't await faulted task , exception stored in task never rethrown.

you can create debugger break in both methods checking thrown column on common language runtime exceptions in settings (debug => exceptions):

c# .net task-parallel-library async-await

No comments:

Post a Comment