Имитация асинхронного (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
        );
}
Теги: