Имитация асинхронного (Async) Deadlock
Редактировал(а) Alexandr Fokin 2024/03/23 17:02
В данном примере мы имитируем ограничение на использование одного потока (которые возникает в некоторых типах приложений, SynchronizationContext | Контекст синхронизации). После этого мы блокируем поток синхронным ожидаем, из-за чего асинхронная задача не может выполнить продолжение (continuation), т.к. она тоже запланирована на выполнение в этом (заблокированном) потоке. | |
Асинхронность. Async Await Проблемы | |
Task Factory SynchronizationContext | Контекст синхронизации | |
[TestMethod] public async Task AsyncDeadlockTest1Async() { var delay = TimeSpan.FromMilliseconds(100); var delay2 = TimeSpan.FromMilliseconds(500); async Task TestMethodAsync() { await Task.Delay(delay); } ConcurrentExclusiveSchedulerPair scheduler = new ConcurrentExclusiveSchedulerPair(); TaskFactory factory = new TaskFactory(scheduler: scheduler.ExclusiveScheduler); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); AsyncAutoResetEvent startLock = new AsyncAutoResetEvent(set: false); var task = factory.StartNew( () => { startLock.Set(); var testTask = TestMethodAsync(); //Deadlock testTask.Wait( cancellationTokenSource.Token ); NotCorrectActionError.Throw("Данный код нет должен выплняться из-за Deadlock"); //Аналогичено, но без токена //testTask // .GetAwaiter() // .GetResult(); //NotCorrectActionError.Throw("Данный код нет должен выплняться из-за Deadlock"); } ); await startLock.WaitAsync(); cancellationTokenSource.CancelAfter(delay2); await Assert.ThrowsExceptionAsync<OperationCanceledException>( async () => await task ); } |