首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >任务取消和TaskContinuationOptions

任务取消和TaskContinuationOptions
EN

Stack Overflow用户
提问于 2013-03-25 00:25:32
回答 1查看 8.2K关注 0票数 4

我昨天刚被介绍给任务(TPL),所以我尝试做一个小的示例项目,以便了解如何使用它们。

我的示例项目是使用开始按钮设置的,该按钮开始递增进度条。取消任务的第二个按钮。一个文本框用于报告使用TaskContinuationOptions.OnlyOnRanToCompletion的延续何时调用,另一个文本框用于报告使用TaskContinuationOptions.OnlyOnCanceled的延续何时被调用。

我可以创建和执行一个任务,但取消它的方式允许继续使用TaskContinuationOptions.OnlyOnCanceled标志触发,这是一个问题。

我创建的任务如下:

代码语言:javascript
复制
private void StartTask()
{
    CancellationTokenSource tokenSource = new CancellationTokenSource();
    CancellationToken token = tokenSource.Token;

    Task task = null;
    task = Task.Factory.StartNew(() => DoWork(tokenSource), tokenSource.Token);

    //A list<CancellationTokenSource> so that I can cancel the task when clicking a button on the UI Thread.
    MyTasks.Add(tokenSource);

    Task completed = task.ContinueWith(result => TaskCompleted(), TaskContinuationOptions.OnlyOnRanToCompletion);
    Task canceled = task.ContinueWith(result => TaskCanceled(), TaskContinuationOptions.OnlyOnCanceled);
}

我取消这项任务如下:

代码语言:javascript
复制
private void CancelTasks()
{
    foreach (CancellationTokenSource tokenSource in MyTasks)
    {
        tokenSource.Cancel();                
    }
}

我的工作人员职能如下:

代码语言:javascript
复制
private void DoWork(CancellationTokenSource tokenSource)
{
    if (progressBar1.InvokeRequired)
    {
        progressBar1.Invoke(new Action(() => DoWork(tokenSource)));
        return;
    }

    try
    {
        bool dowork = true;
        while (dowork)
        {
            tokenSource.Token.ThrowIfCancellationRequested();

            if (progressBar1.Value == progressBar1.Maximum)
            {
                dowork = false;
            }
            Thread.Sleep(1000);
            progressBar1.PerformStep();
            Application.DoEvents();
        }
        countCompleted++;
    }
    catch (OperationCanceledException)
    {                
    }
}

在我读过的其他文章中,有人建议使用tokenSource.Token.ThrowIfCancellationRequested()来设置由TaskContinuationOptions.OnlyOnCanceled评估的条件。

我所看到的例子中,没有一个包括使用:

代码语言:javascript
复制
catch (OperationCanceledException)
{
}

但是,如果没有它,程序将在调用tokenSource.Cancel()时停止;

目前,当我调用tokenSource.Cancel()时,TaskContinuationOptions.OnlyOnRanToCompletion的延续将运行,而不是TaskContinuationOptions.OnlyOnCanceled。

显然我做得不对。

编辑

在进一步阅读时,我发现一条评论说:

"catch (OperationCanceledException) {}将任务的状态设置为RanToCompletion,而不是已取消的状态“

因此,删除catch (OperationCanceledException) {}允许将任务的状态设置为已取消,但程序在OperationCanceledException上中断,但如果我接着继续执行中断,则TaskContinuationOptions.OnlyOnCanceled的延续任务将运行,这很好。

但是,如何调用tokenSource.Token.ThrowIfCancellationRequested(),而不允许程序中断,同时允许将任务状态设置为“取消”?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-25 09:38:52

就调试器和防止调试器中断所需的选项而言,上面的注释是正确的。但是,下面将给您提供一个更好的示例,说明如何使用延续,以及如何处理从这些延续中的任务引发的异常.

一个延续可以找出一个异常是否是由前置任务的Task异常属性引发的。下面将NullReferenceException的结果打印到控制台

代码语言:javascript
复制
Task task1 = Task.Factory.StartNew (() => { throw null; });
Task task2 = task1.ContinueWith (ant => Console.Write(ant.Exception());

如果task1抛出一个异常,而这个异常没有被延续捕获/查询,那么它就被认为是未处理的,并且应用程序会死掉。有了连续性,就可以通过Status关键字建立任务的结果了。

代码语言:javascript
复制
asyncTask.ContinueWith(task =>
{
    // Check task status.
    switch (task.Status)
    {
        // Handle any exceptions to prevent UnobservedTaskException.             
        case TaskStatus.RanToCompletion:
            if (asyncTask.Result)
            {
                // Do stuff...
            }
            break;
        case TaskStatus.Faulted:
            if (task.Exception != null)
                mainForm.progressRightLabelText = task.Exception.InnerException.Message;
            else
                mainForm.progressRightLabelText = "Operation failed!";
        default:
            break;
    }
}

如果不使用连续,则必须在try/catch块中等待任务,或者在try/catch块中查询任务的Result

代码语言:javascript
复制
int x = 0;
Task<int> task = Task.Factory.StartNew (() => 7 / x);
try
{
    task.Wait();
    // OR.
    int result = task.Result;
}
catch (AggregateException aggEx)
{
    Console.WriteLine(aggEx.InnerException.Message);
}

希望这能有所帮助。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15605860

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档