7

Semaphore の WaitOne(Int32) メソッドのMSDN ドキュメントでは、ゼロの値を指定すると、スロットが開くのを待たずにメソッドがすぐに戻ると書かれています。SemaphoreSlimバージョンのドキュメントには、同じことは書かれていません。SemaphoreSlim はこの動作を共有しますか?

これを自分でテストするタイミングを保証する方法がわかりません。

4

1 に答える 1

10

タイムアウト 0 を渡した場合は、SemaphoreSlim.Wait戻る前に常にスロットの取得を試みます。数回の操作とSpinOnce.

編集: 明確化:これはおそらく と同じ見かけの動作Semaphoreです。のドキュメントからSemaphore

待機ハンドルの状態をテストし、すぐに戻ります

ただしSemaphoreSlim、Wait メソッドを使用すると、 を使用してスロットを開く機会が与えられますSpinOnce

(編集終了)

また、SemaphoreSlimスロットの取得を試みる前に、いくつかの操作を実行します。これらの 1 つは であるMonitor.Enterため、その時点で待機中または解放中の他のスレッドを待機できます。したがって、必ずしもすぐに戻るとは限りません。

私が知る限り、イベントの順序は次のとおりです。

  1. 作成するCancellationTokenRegistration
  2. 使用可能なスロット数が 0の場合、 (または の場合はSpinWait.SpinOnceスキップします) (編集: ステップ 2 がステップ 5 と同じテストを実行することを強調するために、これを太字にしました。最終テストと終了NextSpinWillYieldtrue
  3. ロックに入るための呼び出しMonitor.Enter(Release と WaitAsync が入るのと同じロック)
  4. 内部のwaitCountを1増やします
  5. 使用可能なスロット数が 0 の場合、 waitCount を 1 減らしてロックを終了し、戻りますfalse
  6. ここまで来て空きスロットがある場合:
    • 利用可能なスロット数を 1 減らす (意味: スロットを獲得する)
    • AvailableWaitHandle使用されていて、使用可能なスロット カウントが再び 0 になった場合は、の下の waitHandle をリセットします。
    • waitCount を 1 減らす
    • ロックを終了する
    • 廃棄するCancellationTokenRegistration
    • 戻るtrue

(ゼロ以外のタイムアウトを使用している他のスレッドは、 を呼び出してカウンターを保護するために使用されるロックを断続的に解放および取得することに注意してください。そのMonitor.Waitため、タイムアウト 0 で永遠に待機することはなく、非常に短い時間だけです。)

したがって、スロットに開く機会を与えるため、SemaphoreSlimまったく同じ 0 タイムアウト動作を と共有しているようには見えません。(セマフォのインスタンス化を変更するだけで古いコードをアップグレードするときにコードがコンパイルされないようにするためのand -Sempahoreがある理由かもしれません。したがって、動作をチェックする必要があります)。Semaphore.WaitOneSemaphoreSlim.Wait

記事Semaphore vs. SemaphoreSlimでは、この動作は強調されておらず、2 つの基本的な違いのみが強調されています。

サイドノート:

興味深いことに、その参照には次のようにも記載されています

[SemaphoreSlim] はサポートしていませ... 同期のための待機ハンドルの使用

それでも、 SemaphoreSlim.AvailableWaitHandleのドキュメントには別の言い方があります。

于 2013-05-07T12:35:14.503 に答える