c# - C# 中 Manual/AutoResetEvent 的轻量级替代品

标签 c# multithreading autoresetevent manualresetevent

我已经编写了我希望是在 C#/.NET 中使用 ManualResetEvent 和 AutoResetEvent 类的轻量级替代方法。这背后的原因是在没有使用内核锁定对象的情况下拥有类似事件的功能。

虽然代码似乎在测试和生产中都运行良好,但让这种事情适用于所有可能性可能是一项艰巨的任务,我会谦虚地请求 StackOverflow 人群对此提出任何建设性意见和/或批评。希望(经过审查)这对其他人有用。

用法应类似于 Manual/AutoResetEvent 类,其中 Notify() 用于 Set()。

这里是:

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。

关于c# - C# 中 Manual/AutoResetEvent 的轻量级替代品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2816903/

相关文章:

java - 不同线程中的 DecimalFormat.format(double)

c - 线程开销性能

c# - AutoResetEvent 在信号前触发

C# 外部类线程 (AutoResetEvent)

c# - 多写者单读者并发模型的最有效锁?

c# - 为什么 SqlQuery 比在 View 上使用 LINQ 表达式快很多?

multithreading - 一个进程之间的线程可见性

c# - 如何使用编译后的 lambda 函数对运行时生成的类型进行分组

c# - 统一引擎 : Which component called a running script?

c# - AutoResetEvent 设置后立即复位