取消正在执行的任务我有我需要依次处理(但在一个单独的工作线程,从而保持用户界面的响应)的项目清单。重要的是要注意的是,这些项目可以运行很长时间(5 - 10秒)。在任务队列
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());
}
现在,我使用的是CancellationToken
取消队列的处理(有一个“取消处理”按钮)。
的问题是,这并没有取消目前正在执行的任务。如果CancellationTokenSource.Cancel()
被调用,那么所有的等待队列中要执行的任务将被取消和他们的项目的currentItem.State
将被设置为State.Cancelled
,这是正确的。问题是取消时正在执行的任务将继续执行,直至完成,然后设置为State.Complete
或State.Failed
。这并不理想,原因有两个:(1)取消后任务仍在运行,(2)状态未设置为State.Cancelled
,因为t.IsCanceled
不正确。
有没有办法对我来说,安全地取消/停止当前正在执行的任务?
是的,只是代码正是你想要的。没有魔法,秘密简单的方法。您必须指定将支持中断的每个任务在哪里以及如何中断,可能通过在方便的位置检查其任务结构来查看它是否被取消。 –
在你的'ProcessItem'方法中,你可以传入'CancellationToken'并定期调用'ThrowIfCancellationRequested'。 –
问题是我无法以任何方式重新设计ProcessItem()。 – davenewza