Сценарии - Имитация асинхронного (Async) Deadlock 

Page / - Изменено Alexandr Fokin в 2023/01/11 14:50 

Имитация асинхронного (Async) Deadlock 
Изменено Alexandr Fokin
в 2023/01/11 14:50

Оглавление

 	В данном примере мы имитируем ограничение на использование одного потока (которые возникает в некоторых типах приложений, 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
        );
}