Как отменить задачу, которая не выполняет никаких циклических операторов

У меня есть асинхронная задача, которая выполняет функцию. Функция не содержит никаких циклических операторов, но вместо этого она выполняет серию команд SQL на сервере SQL. Теперь у меня есть кнопка в моем окне, которая может отменить эти операции SQL. Другими словами, отмените всю асинхронную задачу.

Я знаю, что этот метод потребует CancellationTokenSource и CancellationToken для отмены задачи, но я видел много примеров в Интернете, и все они показывают, что функция, которую выполняет эта задача, содержит операторы цикла, в которых они проверяют наличие IsCancellationRequested булево свойство. Но в моем случае это не так. В моей функции нет операторов цикла, в которых я могу проверить это логическое свойство.

Пожалуйста, предложите любой метод / технику.

Любая помощь будет весьма заметна...

Спасибо заранее...

3 ответа

Ну, на самом деле есть только три основных программных потока: последовательность (шаг 1, шаг 2 и т. Д.), Выбор (операторы типа if) и итерация (циклы).

Если у вас нет петель, все, что вам осталось, это выбор и последовательность. Это означает, что ваш код, вероятно, будет выглядеть примерно так (псевдокод, очевидно):

perform sql (statement1)
if IsCancellationRequested: return

perform sql (statement2)
if IsCancellationRequested: return
:
:
perform sql (statementN)
if IsCancellationRequested: return

Другими словами, без петель нет единого удобного места, где можно поставить чек, где он будет вызываться много раз, и вам придется вызывать его много раз самостоятельно. Нет реальной разницы между этим и вызовом в цикле, с точки зрения количества раз, которое он вызывается.


Если ваша проблема заключается в том, что вам не нравится идея, что в вашем исходном коде так много проверок, вы можете создать функцию, которая сделает это за вас, что-то вроде:

def execSql (sqlStatement):
    perform sql (sqlStatement)
    return IsCancellationRequested

тогда ваши строки становятся:

if (perform sql (statement1)): return
if (perform sql (statement2)): return
:
if (perform sql (statementN)): return

Теперь вы, вероятно, можете добавлять циклы, помещая операторы в какую-то коллекцию, и таким образом вам придется кодировать только одну проверку / возврат. Но это означает более существенные изменения в том, как вы делаете вещи сейчас.

Так сделай их!

Простой пример (Вы можете расширить его как хотите):

List<string> _sqls = new List<string>();
_sqls.Add("Select ... ");
_sqls.Add("Update ... ");
_sqls.Add("Select ... ");

foreach (var sql in _sqls)
{
   Execute(sql);
   if (IsCancellationRequested)
   {
      // Make some rollback
      return;
   }
} 

Для лучшего опыта вы можете использовать List<Func<..>>, List<Action<..>> вместо List<string> или даже придумать шаблоны проектирования Query, Builder, Factory Method.

Вы должны проверять это всякий раз, когда вам нужно в вашем коде. Ваш пример (тот, который вы видели) имеет для, так что он проверяет отмену на каждой итерации. Поскольку у вас нет для, вам придется вручную выбирать, когда вы хотите проверить, если пользователь отменить его. Поскольку у вас есть запросы, может быть, после каждого запроса или каждые 2 или 3 запроса. Когда тебе это нужно.

Другие вопросы по тегам