14

クラスがマルチスレッド化された別のクラスからのイベント呼び出しをリッスンする Visual Studio 2008 C# .NET 3.5 プロジェクトがあります。イベントが最大 10 個のスレッドへの同時アクセスのみを許可するようにする必要があります。11 番目のスレッドは、10 のうちの 1 つが終了するまでブロックする必要があります。

myobj.SomeEvent += OnSomeEvent;

private void OnSomeEvent(object sender, MyEventArgs args)
{
    // allow up to 10 threads simultaneous access. Block the 11th thread.
    using (SomeThreadLock lock = new SomeThreadLock(10))
    {         
        DoUsefulThings(args.foo);
    }
}

他のMyObjクラスを制御できないため、そこにスレッドプールを実装できません。

これを実装する最良の方法は何ですか?

ありがとう、ポールH

4

3 に答える 3

21

Semaphore クラスが必要です。つまり、指定された数の呼び出し元だけがいつでも通過できるようにするロックです。

スレッドの作成は制御できないため、デッドロックの状況に注意する必要があります。セマフォは再入可能性に対応していません。特定のスレッドがセマフォに複数回入ると、複数のスロットが必要になります。そのため、呼び出し元の各スレッドがセマフォに複数回入ると、デッドロックが発生する可能性があります。

于 2012-04-16T15:18:57.647 に答える
9

これにはを使用Semaphoreします。コンストラクターのパラメーターは、クラスに導入されたばかりのパラメーターには少し混乱します。最初のパラメーターは、現在通過できるスレッドの初期数を指定します。2番目のパラメーターは、任意の時点で許可されるスレッドの最大数を指定します。

myobj.SomeEvent += OnSomeEvent;
Semaphore semaphore = new Semaphore(10, 10);

private void OnSomeEvent(object sender, MyEventArgs args)
{
  semaphore.WaitOne();
  try
  {
    DoUsefulThings(args.foo);
  }
  finally
  {
    semaphore.Release();
  }
}
于 2012-04-16T15:31:30.227 に答える
3

これにはセマフォを使用するのが通例です。10単位に初期化します。DoUsefulThings() の前に 1 ユニット分 wait() し、1 ユニット後に signal() します。

于 2012-04-16T15:19:51.553 に答える