6

私は、C#/。NETでManualResetEventクラスとAutoResetEventクラスを使用する代わりの軽量な方法を作成しました。この背後にある理由は、カーネルロックオブジェクトを使用することの重みなしに、イベントのような機能を持つことでした。

コードはテストと本番の両方でうまく機能しているように見えますが、すべての可能性に対してこの種のことを正しく行うことは骨の折れる作業である可能性があり、これについてStackOverflowの群衆から建設的なコメントや批判を謙虚に要求します。うまくいけば(レビュー後)これは他の人に役立つでしょう。

使用法は、Set()に使用されるNotify()を使用した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);
    }
  }
}
4

4 に答える 4

4

これは、Win32 イベントが高価であるという前提から機能します。そうではありません。イベントよりも安いと私が考えることができるものはほとんどありません。これがそうであることの主なヒントは、.NET 設計者が、Win32 イベントを使用して MRE と ARE を実装することをお勧めすると判断したことです。

交換の真のコストは、スレッドの競合が発生し、その原因がわからないときに経験する主要な FUD です。

于 2010-05-12T11:49:39.927 に答える
2

AutoResetEvent のパフォーマンスを最適化する 1 つの方法は、その状態 (シグナルあり/シグナルなし) を独自の変数に保持することです。そのため、カーネルに移動して実際にイベント オブジェクトを使用する前に、アプリケーション変数の状態を確認してそのままにしておくことができます。ずっとユーザーモード。数か月前に、この概念のデモンストレーション
を 投稿しました。

于 2010-11-04T18:14:38.557 に答える
1

残念ながら、Win32 同期プリミティブを考えると、正しい Monitor 実装はかなり重いものになります。私の最初の疑念は、「ロック」はイベントよりもリソースの使用が重いということです (そして、イベントの上に構築されている可能性があります)。

于 2010-05-12T13:18:35.930 に答える
0

一般に、同期は低速であるため、避けるのが最善です。

ただし、速度には大きな違いがあります。

CPU がサポートするInterlocked Exchangeが最も高速ですが、単純なブール値のフラグは依然として AutoresetEvent より優れています。

完全なコード サンプルと、AutoResetEvent と代替のパフォーマンス比較については、こちらを確認してください。

于 2013-04-07T22:51:10.370 に答える