取消任务队列中正在执行的任务

时间:2012-09-13 10:08:19

标签: c# .net multithreading asynchronous task-parallel-library

我有一个项目列表,我需要按顺序处理(但在一个单独的工作线程上,以保持UI响应)。需要注意的重要一点是,这些物品可以运行很长时间(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.CompleteState.Failed。这有两个原因并不理想:(1)取消后任务仍在运行,(2)状态未设置为State.Cancelled,因为t.IsCanceled不正确。

我有办法安全取消/停止当前正在执行的任务吗?

2 个答案:

答案 0 :(得分:4)

任务支持优雅的取消模式。 CancellationToken只是令牌。它不会中断任何正在执行的代码或中止线程。您应该自己在任务正文中检查此令牌。

要记住的一点是:如果您想取消当前任务,请通过CancellationToken.ThrowIfCancellationRequested方法取消,而不仅仅是退出任务正文。

答案 1 :(得分:2)

查看有关“任务取消”的msdn文章。 http://msdn.microsoft.com/en-us/library/dd997396.aspx 您所要做的就是检查Task的工作方法中是否取消了Task。将检查取消代码放在方法的关键区域。 希望它有所帮助!