如何检测事件处理程序并释放它?

时间:2012-10-01 15:00:11

标签: c# events event-handling event-hooking

假设我有一个类说一个viewmode类mvvm。然后为此vm创建了一些事件处理程序。然后它可以被许多其他不同情况的人使用。

因此,如果我有一个myvm实例,我想检测是否有任何事件处理程序连接并想要释放它以解决内存问题。

从myvm中执行此操作的一般方法是什么,例如,我可能没有myvm的源代码?

2 个答案:

答案 0 :(得分:2)

事件的设计使得声明它们的类之外的代码无法访问底层委托。例如,根据C# Language specification(强调我的)中的“10.8事件”部分:

  

在x + = y或x - = y形式的运算中,当x是事件时   引用发生在包含的类型之外   声明x,操作的结果类型为void(as   反对具有x的类型,其后的值为x   分配)。 此规则间接禁止外部代码   检查事件的基础代理。

因此,找出在课堂外订阅的活动最多可能是“解决”。

如果您有权访问包含该事件的类的来源,并且您希望跟踪与event相关联的代理,请在add中实施removemanually keep track of them in a Dictionary关键字。事件定义和{{3}}。

答案 1 :(得分:0)

如果我理解正确的话。 这个类包装了我使用SocketAsyncEventArgs来解释的未知myvm类,显然我们没有SocketAsyncEventArgs类的源代码。

我包装了SocketAsyncEventArgs类的Completed事件。触发该事件时,将触发_instance_Completed,然后将触发_myvm事件。所以我们需要做的是订阅/取消订阅_myvm事件。

然后我留下一个事件供人们订阅/取消订阅_myvm事件,因为订阅/取消订阅,代表被存储到List中,因此您可以清除 通过调用ClearEvents()方法。

希望它会有所帮助。

    public class WrapperClass
    {
        private EventHandler<SocketAsyncEventArgs> _myEvent;
        private SocketAsyncEventArgs _myvm;
        private List<Delegate> delegates;

        public WrapperClass()
        {
            delegates = new List<Delegate>();
        }

        public void SetInstance(SocketAsyncEventArgs myvm)
        {
            _myvm = myvm;
            _myvm.Completed += new EventHandler<SocketAsyncEventArgs>(_instance_Completed);
        }

        private void _instance_Completed(object sender, SocketAsyncEventArgs e)
        {
            if (_myEvent != null)
            {
                _myEvent(sender, e);
            }
        }

        public event EventHandler<SocketAsyncEventArgs> myEvent
        {
            add
            {
                delegates.Add(value);
                _myEvent = (EventHandler<SocketAsyncEventArgs>)Delegate.Combine(_myEvent, value);
            }
            remove
            {
                delegates.Remove(value);
                _myEvent = (EventHandler<SocketAsyncEventArgs>)Delegate.Remove(_myEvent, value);
            }
        }

        public void ClearEvents()
        {
            foreach (var d in delegates)
            {
            _myEvent = (EventHandler<SocketAsyncEventArgs>)Delegate.Remove(_myEvent, d);
            }
        }
    }