简体   繁体   English

TPL如何正确取消任务

[英]TPL How to Correctly Cancel a Task

I have the following task 我有以下任务

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());

In the method DuplicateSqlProcsFrom(token, mainForm.mainConnection, strDbA, strDbB) I have the standard cancellation detection: 在方法DuplicateSqlProcsFrom(token, mainForm.mainConnection, strDbA, strDbB)我有标准的取消检测:

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

The cancellation event is a button click on the main form, inside the click event I have: 取消事件是点击主表单上的按钮,在我有的点击事件中:

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

but I can seem to catch the AggregateException , what am I doing wrong here? 但我似乎能抓住AggregateException ,我在这里做错了什么?

Edit: Inside the method DuplicateSqlProcsFrom(token, mainForm.mainConnection, strDbA, strDbB) I can catch the OperationCancelledException but I am confused about how to handle it. 编辑:方法内部DuplicateSqlProcsFrom(token, mainForm.mainConnection, strDbA, strDbB)我可以捕获OperationCancelledException但我对如何处理它感到困惑。 All the example I have seen handle the printing of "Operation Cancelled..." etc. on the UI thread within the event that caused the cancel. 我看到的所有示例都在导致取消的事件中处理UI线程上的“取消操作...”等操作。 What is the best way to capture the cancel and pass it back to the UI/calling thread? 捕获取消并将其传递回UI /调用线程的最佳方法是什么?

It most likely has to do with Just My Code mode (defaulted to checked) in Visual Studio. 它很可能与Visual Studio中的“我的代码”模式(默认为已检查)有关。 The debugger is breaking before the TPL can observe the exception. 在TPL可以观察到异常之前,调试器正在中断。 Try unchecking the box and see if that clears things up (Tools->Options->Debugging->General, then un-check the box) 尝试取消选中该框并查看是否清除了(工具 - >选项 - >调试 - >常规,然后取消选中该框)

To get an OperationCancelledException , it needs to be thrown with the same token as the one passed to the Task's constructor: 要获得OperationCancelledException ,需要使用与传递给Task的构造函数的令牌相同的令牌抛出它:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM