Кажется, это общая проблема, но я пока не могу найти решение. Я проверил это в SO
Отмена задания вызывает исключение
Мой абонент:
Private Async Sub btnTestTimer_Click(sender As Object, e As EventArgs) Handles btnTest.Click
_cts = New CancellationTokenSource()
Try
Await Task.Run(AddressOf TestCancellationAsync).ConfigureAwait(False)
Catch cx As OperationCanceledException
MsgBox(String.Format("The following error occurred: {0}", cx.Message), MsgBoxStyle.Critical)
Catch ex As Exception
MsgBox(String.Format("The following error occurred: {0}", ex.Message), MsgBoxStyle.Critical)
End Try
End Sub
Моя задача здесь
Private Async Function TestCancellationAsync() As Task
'Launch a dummy timer which after some time will itself cancel a token and throw
Dim tmr As New System.Timers.Timer(1000)
AddHandler tmr.Elapsed, AddressOf OnTimerElapsed
tmr.Enabled = True
End Function
И функция таймера, которая отменяет и выбрасывает, является
Private Sub OnTimerElapsed(sender As Object, e As ElapsedEventArgs)
Dim tmr As System.Timers.Timer = CType(sender, System.Timers.Timer)
tmr.Enabled = False
Task.Delay(5000) 'After 5 seconds simulate a cancellation
_cts.Cancel() //This is just to cancel from within the timer, actually the cancellation to _cts will happen from another caller which is not shown here
_cts.Token.ThrowIfCancellationRequested()
End Sub
Фактическая программа с асинхронной задачей и отменой здесь не показана, чтобы сохранить пример кратким, но при этом можно было повторить проблему.
Бизнес-требование заключается в том, что при нажатии кнопки запускается асинхронная задача, которая открывает несколько асинхронных функций. Один из них запускает таймер, который будет проверять состояние токена _cts и отменять его при необходимости. Если такая отмена происходит извне на токене _cts, таймер сгенерирует исключение отмены
Вещи, которые я пробовал:
- Я обработал исключение OperationCancelled, но оно по-прежнему не выполняется.
- У меня снят флажок Tools-Options-Debug-General-Enable, только мой код, чтобы увидеть, является ли он Visual Studio. Но все же это сообщается как необработанное исключение PDB
- Я запустил exe извне, как и ожидалось, он завис из-за необработанного исключения
Дайте мне знать, что я здесь делаю неправильно. Мой вызывающий ожидает завершения задачи - так как таймер запускается изнутри задачи, я буду ожидать, что задача не завершена, и любые возникшие исключения будут обнаружены.