ホームページ >バックエンド開発 >C++ >C# でイベントをディスパッチするときに競合状態を回避するにはどうすればよいですか?

C# でイベントをディスパッチするときに競合状態を回避するにはどうすればよいですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2025-01-03 17:03:41231ブラウズ

How to Avoid Race Conditions When Dispatching Events in C#?

イベントディスパッチにおける競合状態

C# のイベントは、次のコードを使用してディスパッチされることがよくあります:

public event EventHandler SomeEvent;
...
{
    ....
    if(SomeEvent!=null)SomeEvent();
}

ただし、マルチスレッド環境では、このアプローチは競合状態を引き起こす可能性があります。これがどのように起こるかは次のとおりです。

  1. スレッド 1 は SomeEvent が null でないかどうかを確認します。
  2. スレッド 2 は SomeEvent から唯一の登録されたデリゲートを削除します。
  3. スレッド 1 は次の処理に進みます。 SomeEvent を呼び出します。null 呼び出しにより例外が発生します。 list.

この同時実行性の問題に対処するためのベスト プラクティスは、null をチェックする前に呼び出しリストを一時変数にコピーすることです。

protected virtual void OnSomeEvent(EventArgs args) 
{
    EventHandler ev = SomeEvent;
    if (ev != null) ev(this, args);
}

このアプローチはスレッドセーフです。なぜなら:

  • Delegate.Combine と Delegate.Remove は、代わりに新しいデリゲート インスタンスを返します。既存のものを変更します。
  • .NET でのオブジェクト参照の割り当てはアトミックです。
  • イベント アクセサー (追加/削除) は同期されます。

呼び出しをコピーすることにより、リストにあるように、コピーの取得後にイベント ハンドラーが削除された場合でも、イベント ハンドラーが確実に呼び出されます。ただし、この解決策は、廃止されたイベント ハンドラーに関する潜在的な状態の問題には対処していないことに注意することが重要です。

以上がC# でイベントをディスパッチするときに競合状態を回避するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。