2012-03-01 9 views
7

にイベントを設定:私はこのようなコードを持ってヌル

public class SomeClass 
{ 
    int _processProgress; 
    public int ProcessProgress 
    { 
     get { return _processProgress; } 
     set 
     { 
      _processProgress = value; 
      if (ProcessProgressChanged != null) 
       ProcessProgressChanged(value); 
     } 
    } 

    public delegate void ProcessProgressChangedEventHandler(int progressPercentage); 
    public event ProcessProgressChangedEventHandler ProcessProgressChanged; 

    public void ClearProcessProgressChangedEvent() 
    { 
     this.ProcessProgressChanged = null; 
    } 
} 

ウィルそれ退会私はClearProcessProgressChangedEvent()メソッドを呼び出すProcessProgressChangedイベント内のすべての方法?

私のコードはC#、フレームワーク4、VS2010 Proでビルドされています、プロジェクトはWinformsにあります。

助けてください。前もって感謝します。

+2

この質問は重複していません。その質問では、イベントに登録されているオブジェクトをnullに設定するよう求めています。イベント自体をnullに設定することを求めているこの質問。 – Wes

答えて

14

これはサブスクライバのリストを有効にクリアすることになります。その場合、次のProcessProgressが設定されるようにハンドラは呼び出されません。 イベントをnullに設定するのではなく、基になるフィールドをnullに設定しています。 C#コンパイラは、単一の宣言を使用して、イベント(サブスクライブ/サブスクライブのないメソッドのペア)とフィールド(ハンドラを格納する)の両方を作成しているだけです。

私のarticle about events and delegatesが役に立ちます。

イベント発生コードは現在スレッドセーフではありません。それがあるか、ないする必要があるかどうか私は知らないが、が使用してを検討するには、お勧めします:

set 
{ 
    _processProgress = value; 
    var handlers = ProcessProgressChanged; 
    if (handlers != null) 
    { 
     handlers(value); 
    } 
} 

そのように最後のハンドラが退会している場合は、NullReferenceExceptionを取得することはありません退化次数後チェックしてください。の前に、が呼び出されます。

+1

ありがとう、また、_thread-safe tip_に感謝します。 –

+0

Jon、匿名のデリゲートをイベントに登録し、後でそれをnullに割り当てることでイベントをクリアすると、ラムダ式などで参照されるオブジェクトのガベージコレクションが妨げられる可能性がありますか? – Apelsin

+1

@Apelsin:正直言ってもっと具体的な例を与える必要があります。おそらく新しい質問です。しかし、イベントの基になるフィールドがnullに設定されている場合、ガベージコレクションを妨げるものは何も見えません。 –

3

はい、イベントの全員の登録を解除します。このhereへ(ビット間接的な私見)参照があります:

すべての加入者がイベントを解除しました、パブリッシャクラス内のイベント インスタンスはnullに設定されています。