1

我有一个需要按顺序处理的项目列表(但在单独的工作线程上以保持 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());
}

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

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

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

4

2 回答 2

5

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

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

于 2012-09-13T10:25:00.180 回答
3

查看这篇关于任务取消的 msdn 文章。http://msdn.microsoft.com/en-us/library/dd997396.aspx 您所要做的就是检查任务是否在任务的工作方法中被取消。将您的支票取消代码放在方法的关键区域。希望能帮助到你!

于 2012-09-13T10:28:47.197 回答