TPL Как правильно отменить задачу - PullRequest
4 голосов
/ 09 марта 2012

У меня есть следующая задача

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

Событие отмены - это нажатие кнопки на главной формевнутри события click у меня есть:

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) Iмогу поймать OperationCancelledException, но я не совсем понимаю, как с этим справиться.Все примеры, которые я видел, обрабатывали печать «Операция отменена ...» и т. Д. В потоке пользовательского интерфейса в событии, которое вызвало отмену.Каков наилучший способ перехватить отмену и передать ее обратно в пользовательский интерфейс / вызывающий поток?

Ответы [ 2 ]

2 голосов
/ 09 марта 2012

Скорее всего, это связано с режимом Just My Code (по умолчанию отмечен) в Visual Studio. Отладчик ломается до того, как TPL сможет наблюдать исключение. Попробуйте снять флажок и посмотреть, все ли в порядке (Инструменты-> Параметры-> Отладка-> Общие, затем снимите флажок)

1 голос
/ 15 марта 2012

Чтобы получить OperationCancelledException, его нужно выбросить с тем же токеном, который был передан конструктору Задачи:

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