Reputation: 40012
I have a list of items which I need to process sequentially (but on a separate worker thread so to maintain UI responsiveness). The important thing to note is that these items can run for a long time (5 - 10 seconds).
Task<bool> currentTask = null;
foreach (var item in items)
{
var currentItem = item;
// Add a new task to the sequential task queue
if (currentTask == null)
currentTask = Task.Factory.StartNew<bool>(() =>
{
return currentItem.ProcessItem();
}, processCancelTokenSource.Token);
else
currentTask = currentTask.ContinueWith<bool>(t =>
{
return currentItem.ProcessItem();
}, processCancelTokenSource.Token);
// Update UI after each task completes
currentTask.ContinueWith(t =>
{
if (t.IsCanceled)
currentItem.State = State.Cancelled;
else
{
if (t.Result)
currentItem.State = State.Complete;
else
currentItem.State = State.Failed;
}
},TaskScheduler.FromCurrentSynchronizationContext());
}
Now, I am using a CancellationToken
to cancel the processing of the queue (there is a "Cancel Processing" button).
The problem is that this does not cancel the Task which is currently being executed. If CancellationTokenSource.Cancel()
is called, then all the tasks waiting to be executed in the queue will be cancelled and their item's currentItem.State
will be set to State.Cancelled
, which is correct. The problem is that the task which was executing at the time of the cancellation will continue to execute until it is finished and then be set to State.Complete
or State.Failed
. This is not ideal for two reasons: (1) the task is still running after the cancellation, (2) the state is not set to State.Cancelled
because t.IsCanceled
is not true.
Is there a way for me to safely cancel/stop the currently executing Task?
Upvotes: 1
Views: 3293
Reputation: 37770
Tasks supports graceful cancellation pattern. CancellationToken
is just a token. It doesn't interrupt any executing code or aborting a thread. You should check this token in task body yourself.
One point to remember: if you want to get your current task cancelled, cancel it via CancellationToken.ThrowIfCancellationRequested
method, not just exiting from task body.
Upvotes: 5
Reputation: 2954
Check this msdn article about Task Cancellation. http://msdn.microsoft.com/en-us/library/dd997396.aspx All you have to do is check if the Task is cancelled inside the Task's working method. Place your check cancellation code in the critical areas of the method. Hope it helps!
Upvotes: 3