2015-10-05 9 views
8

は、私は私が最初にそれがスレッドセーフにする変数に代入せずにイベントを上げるているこの(不完全)クラスを、持っていると言うことができますコレクション内のアイテムを列挙しているときにアイテムを削除するときに起こるような問題が発生する可能性がありますか?ハンドラ内のイベントから退会することはいつでも安全ですか?それから、イベントハンドラを解除しても安全だろう</p> <pre><code>public class Test { public event EventHandler SomeEvent; void OnSomeEvent(EventArgs e) { if (SomeEvent != null) SomeEvent(this, e); } } </code></pre> <p>:

void SomeEventHandler(object sender, EventArgs e) 
{ 
    testInstance.SomeEvent -= SomeEventHandler; 
} 
+0

'testInstance'何ですか? – Tigran

+1

おそらく、 'sender'と同じ' Test'インスタンスでしょう。 BoltClockとして – BoltClock

+1

@Tigranは、.SomeEvent '(テスト)と同じで – Trisibo

答えて

5

を提供したいと考えています。代議員は不変です。これはマルチキャスト代理人にも当てはまります。イベントを呼び出すとき

デリゲートがロードされた後、呼び出されます。デリゲートが格納されているフィールドが変更されている場合、これは既にロードされているデリゲートには影響しません。

それはハンドラからイベントを変更することは安全です。これらの変更は、現在実行中の呼び出しには影響しません。これは保証されています。

このすべては、デリゲートに裏打ちされたイベントに適用されます。 C#とCLRは、何かを行うことができるカスタムイベントをサポートしています。

+0

はい、私は間違いなくそれから始めたはずです:代議員は不変であり、これが重要です! +1 –

4

それは安全だろう、しかし、ちょうどSomeEventHandlerのコードは一度だけ実行されることを保証するものではありません知っています。マルチスレッドコードを使用している場合、競合状態が発生する可能性があります。

編集: イベントから退会すると、舞台裏で、デリゲートのリストを生成するために、デリゲートを結合します。イベントは、デリゲートの組み合わせでスレッドの安全性を保証するためにロックを使用していること

注意(詳細の多くはthat article by Jon Skeet the man himselfで見つけることができます)。イベントにデリゲートを結合すると、デリゲートの結果のリストが表示されます。ただし、イベントを開催する場合、ではなく、が保証されているのは、結合されたデリゲートの最新バージョンが使用されるということです。 (スレッドセーフイベントを参照してください)、これはイベントがイベントの内側からフックされていないという事実とは無関係です。

イベントは(ほとんどの場合)、デリゲートに基づいています:

は、私は私の編集は、他の答えを少し明確にするために十分な解明:)

+0

これに加えて、私は通常、それを購読する前にイベントからフックを外します。 SomeEventHandlerが一度だけ実行されることを確認するだけです。 – tier1

+1

これはなぜ安全であるかに関する証拠や引用を提供できますか? –

+0

絶対に。私は答えを編集しました。お役に立てれば。 –

関連する問題

 関連する問題