Вызов CancellationTokenSource.Cancel никогда не возвращает результат.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Вызов CancellationTokenSource.Cancel никогда не возвращает результат.

Сообщение Anonymous »

У меня ситуация, когда вызов CancellationTokenSource.Cancel никогда не возвращает результат. Вместо этого после вызова Cancel (и до его возврата) выполнение продолжается с кодом отмены кода, который отменяется. Если отменяемый код впоследствии не вызывает какой-либо ожидающий код, то вызывающая сторона, которая первоначально вызвала Cancel, никогда не получит обратно управление. Это очень странно. Я бы ожидал, что Cancel просто запишет запрос на отмену и немедленно вернет результат, независимо от самой отмены. Тот факт, что поток, в котором вызывается Cancel, в конечном итоге выполняет код, принадлежащий отменяемой операции, и делает это перед возвратом к вызывающей стороне Cancel, выглядит как ошибка в платформе.

Вот как это происходит:
  • Есть кусок кода, назовем его «рабочим кодом», который ожидает некоторый асинхронный код. Для простоты предположим, что этот код ожидает Task.Delay:

    Код: Выделить всё

    try
    {
    await Task.Delay(5000, cancellationToken);
    // …
    }
    catch (OperationCanceledException)
    {
    // ….
    }
    
Непосредственно перед тем, как «рабочий код» вызывает Task.Delay, он выполняется в потоке T1.Продолжение (то есть строка, следующая за «await» или блоком внутри catch) будет выполнено позже либо в T1, либо, возможно, в каком-то другом потоке, в зависимости от ряда факторов.
  • Есть еще один фрагмент кода, назовем его «клиентский код», который решает отменить Task.Delay. Этот код вызывает cancelToken.Cancel. Вызов Cancel выполняется в потоке T2.
Я ожидаю, что поток T2 продолжит работу, вернувшись к вызывающему объекту. Отменить. Я также ожидаю, что содержимое catch (OperationCanceledException) будет выполнено очень скоро в потоке T1 или в каком-либо другом потоке, кроме T2.

То, что происходит дальше, удивительно. . Я вижу, что в потоке T2 после вызова Cancel выполнение немедленно продолжается с блока внутри catch (OperationCanceledException). И это происходит, пока Cancel все еще находится в стеке вызовов. Это как если бы вызов Cancel был перехвачен кодом, который отменяет его. Вот снимок экрана Visual Studio, показывающий этот стек вызовов:

Изображение


Больше контекста

Вот еще немного контекста о том, что фактический код делает:
Существует «рабочий код», который накапливает запросы. Запросы отправляются неким «клиентским кодом». Каждые несколько секунд «рабочий код» обрабатывает эти запросы. Обработанные запросы исключаются из очереди.
Однако время от времени «клиентский код» решает, что достиг точки, когда требуется немедленная обработка запросов. Чтобы сообщить об этом «рабочему коду», он вызывает метод Jolt, который предоставляет «рабочий код». Метод Jolt, вызываемый «клиентским кодом», реализует эту функцию путем отмены Task.Delay, который выполняется основным циклом кода работника. В коде работника Task.Delay отменен, и он приступает к обработке запросов, которые уже были в очереди.

Фактический код был упрощен до простейшей формы и код доступен на GitHub.

Среда

Проблему можно воспроизвести в консольных приложениях, фоновых агентах для универсальных приложений для Windows и фоновых агентах для универсальных приложений для Windows Phone 8.1.

Проблема не может быть воспроизведена в универсальных приложениях для Windows, где код работает так, как я ожидал, и вызов Cancel возвращается немедленно.

Подробнее здесь: https://stackoverflow.com/questions/314 ... er-returns
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Как использовать CancellationTokenSource в Parallel.ForEachAsync
    Anonymous » » в форуме C#
    0 Ответы
    35 Просмотры
    Последнее сообщение Anonymous
  • Как использовать CancellationTokenSource в Parallel.ForEachAsync
    Anonymous » » в форуме C#
    0 Ответы
    33 Просмотры
    Последнее сообщение Anonymous
  • Утечки памяти CancellationTokenSource+CallBackNode (10 МБ/мин)
    Anonymous » » в форуме C#
    0 Ответы
    15 Просмотры
    Последнее сообщение Anonymous
  • Как убить/отменить/остановить запуск будущего исполнителя в Python ThreadPoolExecutor? Future.cancel() возвращает False
    Anonymous » » в форуме Python
    0 Ответы
    78 Просмотры
    Последнее сообщение Anonymous
  • Job.Cancel() не отменяет сопрограмму
    Anonymous » » в форуме Android
    0 Ответы
    12 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»