Исходный код вики Имитация асинхронного (Async) Deadlock
Редактировал(а) Alexandr Fokin 2024/03/23 17:02
Последние авторы
author | version | line-number | content |
---|---|---|---|
1 | | |В данном примере мы имитируем ограничение на использование одного потока (которые возникает в некоторых типах приложений, [[SynchronizationContext ~~| Контекст синхронизации>>doc:Разработка.NET.C#.Многопоточность и асинхронность.Асинхронность\. Async Await.SynchronizationContext | Контекст синхронизации.WebHome]]). | ||
2 | После этого мы блокируем поток синхронным ожидаем, из-за чего асинхронная задача не может выполнить продолжение (continuation), т.к. она тоже запланирована на выполнение в этом (заблокированном) потоке. | ||
3 | | |[[Асинхронность. Async Await>>doc:Разработка.NET.C#.Многопоточность и асинхронность.Асинхронность\. Async Await.WebHome]] | ||
4 | [[Проблемы>>doc:Разработка.NET.C#.Многопоточность и асинхронность.Асинхронность\. Async Await.Проблемы.WebHome]] | ||
5 | | |[[Task Factory>>doc:Разработка.NET.C#.Многопоточность и асинхронность.Task Factory.WebHome]] | ||
6 | [[SynchronizationContext ~~| Контекст синхронизации>>doc:Разработка.NET.C#.Многопоточность и асинхронность.Асинхронность\. Async Await.SynchronizationContext | Контекст синхронизации.WebHome]] | ||
7 | | |{{code language="C#"}}[TestMethod] | ||
8 | public async Task AsyncDeadlockTest1Async() | ||
9 | { | ||
10 | var delay = TimeSpan.FromMilliseconds(100); | ||
11 | var delay2 = TimeSpan.FromMilliseconds(500); | ||
12 | |||
13 | async Task TestMethodAsync() | ||
14 | { | ||
15 | await Task.Delay(delay); | ||
16 | } | ||
17 | |||
18 | ConcurrentExclusiveSchedulerPair scheduler = new ConcurrentExclusiveSchedulerPair(); | ||
19 | TaskFactory factory = new TaskFactory(scheduler: scheduler.ExclusiveScheduler); | ||
20 | |||
21 | CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); | ||
22 | AsyncAutoResetEvent startLock = new AsyncAutoResetEvent(set: false); | ||
23 | |||
24 | var task = factory.StartNew( | ||
25 | () => | ||
26 | { | ||
27 | startLock.Set(); | ||
28 | |||
29 | var testTask = TestMethodAsync(); | ||
30 | |||
31 | //Deadlock | ||
32 | testTask.Wait( | ||
33 | cancellationTokenSource.Token | ||
34 | ); | ||
35 | NotCorrectActionError.Throw("Данный код нет должен выплняться из-за Deadlock"); | ||
36 | |||
37 | //Аналогичено, но без токена | ||
38 | //testTask | ||
39 | // .GetAwaiter() | ||
40 | // .GetResult(); | ||
41 | //NotCorrectActionError.Throw("Данный код нет должен выплняться из-за Deadlock"); | ||
42 | } | ||
43 | ); | ||
44 | |||
45 | await startLock.WaitAsync(); | ||
46 | cancellationTokenSource.CancelAfter(delay2); | ||
47 | |||
48 | await Assert.ThrowsExceptionAsync<OperationCanceledException>( | ||
49 | async () => await task | ||
50 | ); | ||
51 | }{{/code}} |