Легкая альтернатива Manual/AutoResetEvent в C#

Я записал то, что я надеюсь, легкая альтернатива использованию классов 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);
    }
  }
}
5
задан tshepang 13 July 2014 в 22:33
поделиться

2 ответа

Это работает исходя из предположения, что события Win32 являются дорогостоящими. Это не так, я мало что могу придумать, что дешевле, чем мероприятие. Главный намек на то, что это так, - это то, что разработчики .NET решили, что было бы неплохо использовать событие Win32 для реализации MRE и ARE.

Истинная стоимость вашей замены - это главный FUD, с которым вы столкнетесь, когда у вас будет гонка потоков и вы не знаете, что ее вызывает.

4
ответ дан 14 December 2019 в 13:29
поделиться

К сожалению, правильная реализация монитора довольно тяжеловесный, учитывая примитивы синхронизации Win32. Мое первоначальное подозрение состоит в том, что «блокировка» потребует больше ресурсов, чем событие (и, вероятно, построена поверх события).

1
ответ дан 14 December 2019 в 13:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: