C# 清除或检查C中的事件处理程序#

C# 清除或检查C中的事件处理程序#,c#,C#,我有一些C#代码可以更新对象的一些属性。我定义了一个事件处理程序,以帮助我在更新过程完成时做出响应。不幸的是,我了解到该事件被多次触发。我怀疑这是因为事件处理程序设置的时间不对。目前,其设置如下所示: myObject.Update_Succeeded += new EventHandler(myObject_Update_Succeeded); 由于代码的复杂性,我很难找到它应该设置在哪里。我只想设置之前未设置的事件处理程序。因此,我想做这样的事情: ClearEventHandlers(m

我有一些C#代码可以更新对象的一些属性。我定义了一个事件处理程序,以帮助我在更新过程完成时做出响应。不幸的是,我了解到该事件被多次触发。我怀疑这是因为事件处理程序设置的时间不对。目前,其设置如下所示:

myObject.Update_Succeeded += new EventHandler(myObject_Update_Succeeded);
由于代码的复杂性,我很难找到它应该设置在哪里。我只想设置之前未设置的事件处理程序。因此,我想做这样的事情:

ClearEventHandlers(myObject);

有没有办法完成我正在尝试的事情


谢谢大家!

您最好在对象初始化时(即在构造函数中)设置事件处理程序。

是的,您可以自定义事件的添加/删除访问器。描述这些访问器。但你可以做一些类似的事情:

class MyClass
{
    private EventHandler _myEvent;

    public event EventHandler MyEvent
    {
        [MethodImpl(MethodImplOptions.Synchronized)]
        add 
        { 
            _myEvent = (EventHandler)Delegate.Combine(_myEvent, value);
        }
        [MethodImpl(MethodImplOptions.Synchronized)]
        remove 
        { 
            _myEvent = (EventHandler)Delegate.Remove(_myEvent, value); 
        }
    }

    public void ClearMyEvent() {
        _myEvent = null;
    }
    ...
}

您应该能够使用下面的减法运算符删除处理程序

myObject.Update_Succeeded -= new EventHandler(myObject_Update_Succeeded);
或者,如果您对此有疑问,可以查看此方法以删除所有事件处理程序


正确的方法应该是在不再使用处理程序后将其与每个事件分离:

public class MyObjectListener
{
     private readonly MyObject _object;
     public class MyObjectListener(MyObject obj)
     {
          _object = obj;
          Attach();
     }

     // adds event handlers
     private void Attach()
     {
         obj.UpdateSucceeded += UpdateSuceededHandler;
         obj.UpdateFailed += UpdateFailedHandler;
     }

     // removes event handlers
     private void Detach()
     {
         obj.UpdateSucceeded -= UpdateSuceededHandler;
         obj.UpdateFailed -= UpdateFailedHandler;
     }

     ...
}
您唯一需要决定的是在何处调用
Detach
方法。例如,您可以在处理程序本身中调用它:

     private void UpdateSuceededHandler(object sender, Data args)
     {
         Detach();
         // do something when it succeeds
     }

     private void UpdateFailedHandler(object sender, Data args)
     {
         Detach();
         // do something when it fails
     }
或者,您可以允许
MyObjectListener
的用户告诉它不再需要侦听附加的对象:

     public void StopListening()
     {
         Detach();
     }

引发事件的对象不应允许其侦听器修改事件调用列表。每个事件侦听器应该只订阅或取消订阅自己的事件处理程序。

我不推荐这种方法。事件监听器不应该有取消订阅其他他们一无所知的事件监听器的自由。@Groo-总的来说,我同意。但有时可能需要一种方法来清除所有听众的干扰。我必须承认,我还没有遇到过这种情况。BCL中没有一个类遵循您描述的模式(到目前为止,我也没有机会在任何开源库中看到过)。@Groo-我也没有,但这并不意味着永远不需要这样做:-)我需要为销毁后回收的游戏对象这样做。在无法从外部清除事件列表的情况下,我必须为每个对象创建并使用至少两个事件-一个用于感兴趣的事件,另一个仅用于在对象被销毁时收到通知,以便它可以从各种事件链中删除其事件处理程序。这种额外的事件处理会降低性能,并且与如上所示的外部重置相比,不会增加任何好处。这种模式并不适用于所有情况,但对于代码为此设置的循环情况,这样做是有意义的。
     public void StopListening()
     {
         Detach();
     }