TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.76K subscribers
Post #1730 1.4K
День 1398. #ЗаметкиНаПолях #AsyncTips
Блокирующие и Асинхронные Сигналы

1. Блокирующие Сигналы
Задача:
требуется отправить уведомление от одного потока другому.

Решение
Самый распространённый и универсальный межпотоковый сигнал — событие с ручным сбросом ManualResetEventSlim. Оно может находиться в одном из двух состояний: установленном или сброшенном. Любой поток может перевести событие в установленное состояние или сбросить его. Поток также может ожидать перехода события в установленное состояние.
Следующие два метода вызываются разными потоками; один поток, использует Wait() и ожидает сигнала от другого, который вызывает Init():
class MyClass
{
private readonly ManualResetEventSlim
_mres = new();
private int _val;

public int Wait()
{
_mres.Wait();
return _val;
}
public void Init()
{
_val = 42;
_mres.Set();
}
}

ManualResetEventSlim является синхронным сигналом, поэтому WaitForInitialization блокирует вызывающий поток до отправки сигнала.

2. Асинхронные Сигналы
Задача:
требуется отправить уведомление от одного потока другому, при этом получатель оповещения должен ожидать его асинхронно.

Решение
Если уведомление должно быть отправлено только один раз, можно использовать TaskCompletionSource<T>. Код-отправитель вызывает TrySetResult, а код-получатель ожидает его свойство Task:
class MyClassAsync
{
private readonly TaskCompletionSource<object?>
_set = new();
private int _val1;
private int _val2;

public async Task<int> WaitAsync()
{
await _set.Task;
return _val1 + _val2;
}
public void Init()
{
_val1 = 42;
_val2 = 69;
_set.TrySetResult(null);
}
}

TaskCompletionSource<T> может использоваться для асинхронного ожидания любой ситуации — в данном случае уведомления от другой части кода. Этот способ хорошо работает, если сигнал отправляется только один раз, но не работает, если сигнал нужно не только включать, но и отключать.

Итого
Сигналы представляют собой механизм уведомлений общего назначения, однако использовать их следует только тогда, когда это действительно уместно. Если «сигнал» представляет собой сообщение, отправляющее некоторые данные между потоками, рассмотрите возможность использования очереди «производитель/потребитель». А если сигналы используются только для координации доступа к общим данным, лучше использовать lock или асинхронную блокировку.

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 12.
  • 👍 13
More from @netdeveloperdiary
  1. Oct 13, 2026День 2813. #ЗаметкиНаПолях #Async Ещё Раз Про Async/Await в C#. Часть 1 1. Почему существу…
  2. Oct 12, 2026День 2812. #Карьера #AI Как Разработчикам Оставаться Полезными, Когда Код Пишет ИИ? По мер…
  3. Oct 11, 2026День 2811. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  4. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  5. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  6. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →