複数のスレッドからの大量の受信データを処理しているとします。特定の基準が満たされたときに、このデータを特定のアクションのトリガーとして機能させたい場合があります。ただし、アクションは再入可能ではありません。したがって、同じトリガーを2回続けてすばやく起動すると、アクションは1回だけ実行されます。
bool
競合状態が発生し、2つ(またはそれ以上)のスレッドが結局同じアクションを同時に実行する可能性があるため、単純なフラグを使用してアクションが現在実行されているかどうかを示すことは、堅牢なソリューションではありません。もちろん、同期オブジェクトのステートメント内bool
は機能します。lock
しかし、私は通常、可能な限りロックを避けることを好みます*。
現在、これらの場合に私が行っているのはAutoResetEvent
、本質的にアトミックスイッチの形式として使用することです。通常、コードは次のようになります。
if (conditionMet && readyForAction.WaitOne(0))
{
try
{
doAction();
}
finally
{
readyForAction.Set();
}
}
これは機能しますが、これはクラスの理想的なユースケースではない可能性があることに気づきましたAutoResetEvent
。これはこの問題の適切な解決策だと思いますか、それとも他のメカニズムを使用する方が理にかなっていますか?
更新:Jonが指摘したMonitor.TryEnter
ように、ロック戦略として使用することは(単純なものではなく、lock
ほぼ同等であると私は信じていますMonitor.Enter
)、非常に簡単です。
if (conditionMet && Monitor.TryEnter(lockObject))
{
try
{
doAction();
}
finally
{
Monitor.Exit(lockObject);
}
}
そうは言っても、私はヘンクの使用するという考えに強く賛成する傾向がありInterlocked
ます。それはそれが得るのと同じくらい簡単に思えます。