Я записал то, что я надеюсь, легкая альтернатива использованию классов ManualResetEvent и AutoResetEvent в C#/.NET. Обоснование позади этого должно было иметь Событие как функциональность без веса использования объекта блокировки ядра.
Хотя код, кажется, работает хорошо и в тестировании и в производстве, разбирание в такого рода вещи для всех возможностей может быть удручающим обязательством, и я кротко запросил бы любые конструктивные комментарии и или критика от толпы StackOverflow на этом. Надо надеяться (после того, как обзор) это будет полезно для других.
Использование должно быть подобно классам Manual/AutoResetEvent с, Уведомляют () используемый для Набора ().
Здесь идет:
using System;
using System.Threading;
public class Signal
{
private readonly object _lock = new object();
private readonly bool _autoResetSignal;
private bool _notified;
public Signal()
: this(false, false)
{
}
public Signal(bool initialState, bool autoReset)
{
_autoResetSignal = autoReset;
_notified = initialState;
}
public virtual void Notify()
{
lock (_lock)
{
// first time?
if (!_notified)
{
// set the flag
_notified = true;
// unblock a thread which is waiting on this signal
Monitor.Pulse(_lock);
}
}
}
public void Wait()
{
Wait(Timeout.Infinite);
}
public virtual bool Wait(int milliseconds)
{
lock (_lock)
{
bool ret = true;
// this check needs to be inside the lock otherwise you can get nailed
// with a race condition where the notify thread sets the flag AFTER
// the waiting thread has checked it and acquires the lock and does the
// pulse before the Monitor.Wait below - when this happens the caller
// will wait forever as he "just missed" the only pulse which is ever
// going to happen
if (!_notified)
{
ret = Monitor.Wait(_lock, milliseconds);
}
if (_autoResetSignal)
{
_notified = false;
}
return (ret);
}
}
}
Это работает исходя из предположения, что события Win32 являются дорогостоящими. Это не так, я мало что могу придумать, что дешевле, чем мероприятие. Главный намек на то, что это так, - это то, что разработчики .NET решили, что было бы неплохо использовать событие Win32 для реализации MRE и ARE.
Истинная стоимость вашей замены - это главный FUD, с которым вы столкнетесь, когда у вас будет гонка потоков и вы не знаете, что ее вызывает.
К сожалению, правильная реализация монитора довольно тяжеловесный, учитывая примитивы синхронизации Win32. Мое первоначальное подозрение состоит в том, что «блокировка» потребует больше ресурсов, чем событие (и, вероятно, построена поверх события).