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

Dav*_*New 1 .net c# 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());
}
Run Code Online (Sandbox Code Playgroud)

现在,我使用 aCancellationToken来取消队列的处理(有一个“取消处理”按钮)。

问题是这不会取消当前正在执行的任务。如果CancellationTokenSource.Cancel()被调用,则队列中等待执行的所有任务将被取消,并且它们的项目currentItem.State将被设置为State.Cancelled,这是正确的。问题是取消时正在执行的任务将继续执行,直到完成然后设置为State.Completeor State.Failed。这并不理想,原因有两个:(1) 任务取消后仍在运行,(2) 状态未设置为State.Cancelled因为t.IsCanceled不是 true。

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

Den*_*nis 5

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

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