Как отменить задачу, которая не выполняет никаких циклических операторов
У меня есть асинхронная задача, которая выполняет функцию. Функция не содержит никаких циклических операторов, но вместо этого она выполняет серию команд 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 запроса. Когда тебе это нужно.