Подтвердить что ты не робот

Как отменить асинхронный вызов?

Как отменить асинхронный вызов?.NET APM, похоже, не поддерживает эту операцию.

У меня есть следующий цикл в моем коде, который порождает несколько потоков в ThreadPool. Когда я нажимаю кнопку на своем пользовательском интерфейсе, мне бы хотелось, чтобы эти потоки (или асинхронные вызовы) заканчивались.

foreach (var sku in skus)
{
    loadSku.BeginInvoke(...
}

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

4b9b3361

Ответ 1

"Флаг отмены" - это способ сделать это, хотя и не глобальный, обязательно. Неизбежной точкой является то, что вам нужен some способ сообщить в поток, что он должен остановить то, что он делает.

В случае BeginInvoke это трудно сделать с чем угодно, кроме глобального флага, потому что работа выполняется в threadpool, и вы не знаете, какой поток. У вас есть несколько вариантов (в порядке предпочтения):

  • Используйте BackgroundWorker вместо BeginInvoke. У этого есть функция отмены, испеченная. Это имеет другие преимущества, такие как мониторинг прогресса, и "Work complete" обратные вызовы. Он также красиво обрабатывает исключения.
  • Используйте ThreadPool.QueueUserWorkItem, передавая объект как состояние, которое имеет метод Cancel(), который устанавливает флаг Cancelled, который может проверить исполняемый код. Конечно, вам нужно будет сохранить ссылку на объект состояния, чтобы вы могли называть Cancel() на нем (что для вас означает BackgroundWorker) - у вас есть компонент в вашей форме. (Благодаря Fredrik для напоминания об этом).
  • Создайте свой собственный делегат ThreadStart, передав объект состояния как с параметром 2.

Ответ 2

Если вы ищете метод TerminateAsnyc, вы его не найдете. Поэтому нет, возможно, нет элегантного способа при использовании Control.BeginInvoke/EndInvoke. Таким образом, я поместил бы логический флаг в поток пользовательского интерфейса и выполнил бы делегат асинхронно проверять этот флаг периодически во время его выполнения.

Однако вы можете проверить использование потоков рабочего потока.

Ответ 3

Есть определенные решения, хотя я не знаю, что я бы назвал их "элегантными".

вы могли бы вызвать прерывание или прерывание в потоке, но они могут иметь некоторые отрицательные побочные эффекты. Лично для чего-то подобного я предпочитаю использовать BackgroundWorker, если это возможно. У этого есть функция Отмена, но она похожа на то, что вы упомянули, - флаг bool в классе, который вы должны периодически проверять в исполняемом коде (по крайней мере, это не глобальный флаг). Это сообщение о прекращении потоков в .NET немного устарело, но просматривает некоторые из ошибок других вариантов, о которых я упоминал выше.