I have a task with a thread that performs some operation in a loop:
static void TaskAction(CancellationToken ct) { while (SomeCondition()) { DoSomeSeriousJob(); ct.ThrowIfCancellationRequested(); } } static void DoSomeSeriousJob() { Console.WriteLine("Serious job started"); Thread.Sleep(5000); Console.WriteLine("Serious job done"); }
I run it and then cancel after a while:
var cts = new CancellationTokenSource(); var task = Task.Factory.StartNew(() => TaskAction(cts.Token), cts.Token); Thread.Sleep(1000); cts.Cancel();
This operation must be performed correctly, I do not want to interrupt it. But I want to send a request to cancel my task and wait until it finishes correctly (by this I mean that it reaches some point in the code). I tried the following approaches:
1. Wait (CancellationToken ct)
try { task.Wait(cts.Token); } catch (OperationCanceledException) { Console.WriteLine("Task cancelled"); }
In this case, the program returns immediately from Wait() . The task continues to run until ThrowIfCancellationRequested() , but if the main thread exits, the task also aborts.
2. Wait ()
try { task.Wait(); } catch (OperationCanceledException) { Console.WriteLine("Task cancelled"); } catch (Exception ex) { Console.WriteLine(ex.ToString()); }
Here, the main thread is waiting for completion, but at the end, an AggregateException inserted with InnerException = TaskCancelledException (not OperationCancelledException ).
3. Check IsCancellationRequested () and no exceptions
static void TaskAction(CancellationToken ct) { while (SomeCondition()) { DoSomeSeriousJob(); if (ct.IsCancellationRequested) break; } }
In this case, no exceptions occur, but the task receives the status RanToCompletion at the end. This is not different from the correct completion when SomeCodition() starts to return false.
All these problems have easy workarounds, but I wonder if maybe I'm missing something. Can anyone advise me on a better solution?