Why throwing an OperationCanceledException gives me different results?

My colleague played with TPL and task cancellation. He showed me the following code:

var cancellationToken = cts.Token;
var task = Task.Run(() =>
{
    while (true)
    {
        Thread.Sleep(300);
        if (cancellationToken.IsCancellationRequested)
        {
            throw new OperationCanceledException();
        }
    }

}, cancellationToken)
    .ContinueWith(t => {
        Console.WriteLine(t.Status);
    });

Thread.Sleep(200);
cts.Cancel();

Printed "Canceled" as expected, but if you simply comment on the while line as follows:

// ..
//while (true)
{
    Thread.Sleep(300);
    if (cancellationToken.IsCancellationRequested)
    {
        throw new OperationCanceledException();
    }
}
//..

you will get "Faulted". I am well aware of the ThrowIfCancellationRequested () method and that I have to pass the cancelationToken in the OperationCanceledException constructor (and this results in a Cancel result in both cases), but I cannot explain why this is happening anyway.

+4
source share
1 answer

, , " Canceled, while?". , , Faulted.

, , Canceled, OperationCanceledException CancellationToken, Task.Run(). Faulted .

, , while, , , . , ?

, ( ) , . IL , while ( IL Console.WriteLine(), , ):

.method public hidebysig instance class [mscorlib]System.Threading.Tasks.Task 
        '<Main>b__1'() cil managed
{
  // Code size       67 (0x43)
  .maxstack  2
  .locals init (class [mscorlib]System.Threading.Tasks.Task V_0,
           bool V_1)
  IL_0000:  nop
  IL_0001:  br.s       IL_003f
  IL_0003:  nop
  IL_0004:  ldstr      "sleeping"
  IL_0009:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_000e:  nop
  IL_000f:  ldc.i4     0x12c
  IL_0014:  call       void [mscorlib]System.Threading.Thread::Sleep(int32)
  IL_0019:  nop
  IL_001a:  ldarg.0
  IL_001b:  ldflda     valuetype [mscorlib]System.Threading.CancellationToken TestSO33850046CancelVsFaulted.Program/'<>c__DisplayClass3'::cancellationToken
  IL_0020:  call       instance bool [mscorlib]System.Threading.CancellationToken::get_IsCancellationRequested()
  IL_0025:  ldc.i4.0
  IL_0026:  ceq
  IL_0028:  stloc.1
  IL_0029:  ldloc.1
  IL_002a:  brtrue.s   IL_003e
  IL_002c:  nop
  IL_002d:  ldstr      "throwing"
  IL_0032:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0037:  nop
  IL_0038:  newobj     instance void [mscorlib]System.OperationCanceledException::.ctor()
  IL_003d:  throw
  IL_003e:  nop
  IL_003f:  ldc.i4.1
  IL_0040:  stloc.1
  IL_0041:  br.s       IL_0003
} // end of method '<>c__DisplayClass3'::'<Main>b__1'

, return, ( - ) Task void. , , ; async, , await, , , , Task. Task.

, , , Task.Run() . Task.Run(Action, CancellationToken) Task.Run(Func<Task>, CancellationToken). , . Action Task , Func<Task> UnwrapPromise<T>, , , OperationCanceledException Canceled Faulted.

while, void. , while () return. , void, Action Run(), OperationCanceledException , , Faulted .

, , CancellationToken OperationCanceledException cancellationToken.ThrowIfCancellationRequested() , , CancellationToken Run(), , , Canceled, .

+3

Source: https://habr.com/ru/post/1616903/


All Articles