【问题标题】:TPL How to Correctly Cancel a TaskTPL 如何正确取消任务
【发布时间】:2012-03-08 20:23:14
【问题描述】:

我有以下任务

cancelSource = new CancellationTokenSource();
token = cancelSource.Token;

string strDbA = textBox1.Text;
string strDbB = textBox2.Text;

// Start duplication on seperate thread. 
asyncDupSqlProcs =
    new Task<bool>(state =>
        UtilsDB.DuplicateSqlProcsFrom(token, mainForm.mainConnection, strDbA, strDbB), "Duplicating SQL Proceedures");
asyncDupSqlProcs.Start();
asyncDupSqlProcs.ContinueWith(task =>
{
    switch (task.Status)
    {
        // Handle any exceptions to prevent UnobservedTaskException.             
        case TaskStatus.Faulted:
            // Error-handling logic...
            break;
        case TaskStatus.RanToCompletion:
            if (asyncDupSqlProcs.Result)
                Utils.InfoMsg(String.Format(
        "SQL stored procedures and functions successfully copied from '{0}' " + 
                    "to '{1}'", strDbA, strDbB));
            break;
        case TaskStatus.Canceled:
            Utils.InfoMsg("Copy cancelled at users request.");
            break;
    }
}, TaskScheduler.FromCurrentSynchronizationContext());

在方法DuplicateSqlProcsFrom(token, mainForm.mainConnection, strDbA, strDbB)我有标准的取消检测:

if (_token.IsCancellationRequested)
    _token.ThrowIfCancellationRequested();

取消事件是主窗体上的一个按钮点击,在点击事件里面我有:

try
{
    cancelSource.Cancel();
    asyncDupSqlProcs.Wait();
}
catch (AggregateException aggEx)
{
    if (aggEx.InnerException is OperationCanceledException)
        Utils.InfoMsg("Copy cancelled at users request.");
}

但我似乎可以捕捉到AggregateException,我在这里做错了什么?

编辑:在方法DuplicateSqlProcsFrom(token, mainForm.mainConnection, strDbA, strDbB) 中我可以捕捉到OperationCancelledException,但我对如何处理它感到困惑。我看到的所有示例都在导致取消的事件中处理 UI 线程上的“操作取消...”等的打印。捕获取消并将其传递回 UI/调用线程的最佳方法是什么?

【问题讨论】:

  • 什么是抛出的异常没有被处理?
  • 嗯,我的测试代码实际上出现了异常。你确定 DuplicateSqlProcsFrom() 方法没有快速退出吗?
  • 这也是从什么背景开始的?另一个线程? UI 线程?
  • 在包含if (_token.IsCancellationRequested) 的方法中,它会抛出OperationCancelException,很好。但是我该怎么办呢?它被新的(后台)线程捕获,但我不确定如何在最后一个 try/catch 块中处理它?
  • 抱歉,不清楚。我将编辑问题...

标签: c# task-parallel-library cancellation


【解决方案1】:

这很可能与 Visual Studio 中的“仅我的代码”模式(默认为选中)有关。调试器在 TPL 可以观察到异常之前中断。尝试取消选中该框,看看是否可以清除(工具->选项->调试->常规,然后取消选中该框)

【讨论】:

    【解决方案2】:

    要获得OperationCancelledException,需要使用与传递给任务构造函数的令牌相同的令牌来抛出它:

    new Task<bool>(state =>
        UtilsDB.DuplicateSqlProcsFrom(token, mainForm.mainConnection, strDbA, strDbB),
            "Duplicating SQL Proceedures", token);
    

    【讨论】:

      猜你喜欢
      • 2012-03-29
      • 1970-01-01
      • 2015-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多