注销事件处理程序
unregistering event handler
我有一个 class 可以在收到某些消息时引发事件。此外,它还可以订阅来自同一 class 的其他实例的消息。 (请参阅下面缩短的 class。)我在注销事件处理程序时遇到问题...
调试时我可以看到 Delegate.Remove 被调用(在替代语法版本中),但没有从调用列表中删除任何内容...
class MyClass
{
private event EventHandler<EventArgs> MessageReceived;
public void SubscribeToMessages(Action<object, EventArgs> eventHandler)
{
this.MessageReceived += new EventHandler<EventArgs>(eventHandler);
}
public void UnsubscribeFromMessages(Action<object, EventArgs> eventHandler)
{
this.MessageReceived -= new EventHandler<EventArgs>(eventHandler);
}
private void MessageFromOtherObject_Received(object sender, EventArgs arg)
{
}
public void StartListeningToObject(MyClass obj)
{
obj.SubscribeToMessages(MessageFromOtherObject_Received);
}
public void StopListeningToObject(MyClass obj)
{
obj.UnsubscribeFromMessages(MessageFromOtherObject_Received);
}
}
void Test()
{
MyClass mainObj = new MyClass();
MyClass otherObj = new MyClss();
mainObj.StartListeningToObject(otherObj);
//...
mainObj.StopListeningToObject(otherObj);
}
所以在调用 StopListentingToObject() 时我可以看到它试图删除处理程序,但它仍然存在,并且事件仍在 mainObj 上触发...
现在根据我所知道的和我读到的
this.MessageReceived -= new EventHandler<EventArgs>(eventHandler);
语法应该工作得很好,但它似乎认为这显然是一个不同的委托。
我做错了什么???
非常感谢您的任何建议!
为什么这么复杂?为什么需要私人活动?保持简单!
class Program
{
static void Main(string[] args)
{
}
void Test()
{
MyClass mainObj = new MyClass();
MyClass otherObj = new MyClass();
mainObj.StartListeningToObject(otherObj);
//...
mainObj.StopListeningToObject(otherObj);
}
}
class MyClass
{
public event EventHandler<EventArgs> MessageReceived;
private void MessageFromOtherObject_Received(object sender, EventArgs arg)
{
//do some work
}
public void StartListeningToObject(MyClass obj)
{
obj.MessageReceived += MessageFromOtherObject_Received;
}
public void StopListeningToObject(MyClass obj)
{
obj.MessageReceived -= MessageFromOtherObject_Received;
}
}
顺便说一句,别忘了触发那个事件!
你的代码被破坏的原因是因为你创建了这两个方法:
public void SubscribeToMessages(Action<object, EventArgs> eventHandler)
{
this.MessageReceived += new EventHandler<EventArgs>(eventHandler);
}
public void UnsubscribeFromMessages(Action<object, EventArgs> eventHandler)
{
this.MessageReceived -= new EventHandler<EventArgs>(eventHandler);
}
而不仅仅是来自事件的 adding/removing 处理程序(这是你应该做的)你实际上在做一些完全不同的事情。
SubscribeToMessages
正在添加一个事件处理程序,该事件处理程序在调用时将调用 eventHandler
委托的 Invoke
方法。
当您调用 UnsubscribeFromMessages
时,您试图删除处理程序,该处理程序的主体是对您已传递的 eventHandler
实例的 Invoke
方法的调用。但是,您将不同的 Action
实例传递给这两个方法调用中的每一个(即使这两个不同的操作都指向相同的 method/object 对),因此您尝试的事件处理程序add/remove 分别指代不同的 Action
个实例,因此不被视为相等。
如果您直接 add/remove 事件处理程序,而不是在第二层间接层中添加一个事件处理程序,该事件处理程序调用一个事件处理程序,该事件处理程序调用实际方法,您会没事的。
或者,您使用的 subscribe/unsubscribe 方法没有与事件不同的委托。让他们接受实际事件类型的代表,这样您就可以简单地 add/remove 他们,这也将删除额外的间接层。
问题在于,已注册的委托人的目标实际上是 eventHandler.Invoke
,而实际上并不是您要委托给的 target/method。然后,当您尝试删除处理程序时,它是针对新委托对象的 Invoke
方法的,因此它们不被视为不相等,并且原始注册仍然存在。你想委派给 MessageFromOtherObject_Received
。共有三个选项
- 直接在
Start
/StopListeningToObject
中做add/remove
- 将
UnsubscribeFrom
/SubscribeToMessages
的参数类型改为EventHandler<EventArgs>
通过
创建一个具有正确target/method的委托
var handler = (EventHandler<EventArgs>)Delegate.CreateDelegate(typeof(EventHandler<EventArgs>), eventHandler.Target, eventHandler.Method);
this.MessageReceived += handler;
使用 UnsubscribeFromMessages
中的类似代码删除处理程序。
我有一个 class 可以在收到某些消息时引发事件。此外,它还可以订阅来自同一 class 的其他实例的消息。 (请参阅下面缩短的 class。)我在注销事件处理程序时遇到问题... 调试时我可以看到 Delegate.Remove 被调用(在替代语法版本中),但没有从调用列表中删除任何内容...
class MyClass
{
private event EventHandler<EventArgs> MessageReceived;
public void SubscribeToMessages(Action<object, EventArgs> eventHandler)
{
this.MessageReceived += new EventHandler<EventArgs>(eventHandler);
}
public void UnsubscribeFromMessages(Action<object, EventArgs> eventHandler)
{
this.MessageReceived -= new EventHandler<EventArgs>(eventHandler);
}
private void MessageFromOtherObject_Received(object sender, EventArgs arg)
{
}
public void StartListeningToObject(MyClass obj)
{
obj.SubscribeToMessages(MessageFromOtherObject_Received);
}
public void StopListeningToObject(MyClass obj)
{
obj.UnsubscribeFromMessages(MessageFromOtherObject_Received);
}
}
void Test()
{
MyClass mainObj = new MyClass();
MyClass otherObj = new MyClss();
mainObj.StartListeningToObject(otherObj);
//...
mainObj.StopListeningToObject(otherObj);
}
所以在调用 StopListentingToObject() 时我可以看到它试图删除处理程序,但它仍然存在,并且事件仍在 mainObj 上触发...
现在根据我所知道的和我读到的
this.MessageReceived -= new EventHandler<EventArgs>(eventHandler);
语法应该工作得很好,但它似乎认为这显然是一个不同的委托。
我做错了什么???
非常感谢您的任何建议!
为什么这么复杂?为什么需要私人活动?保持简单!
class Program
{
static void Main(string[] args)
{
}
void Test()
{
MyClass mainObj = new MyClass();
MyClass otherObj = new MyClass();
mainObj.StartListeningToObject(otherObj);
//...
mainObj.StopListeningToObject(otherObj);
}
}
class MyClass
{
public event EventHandler<EventArgs> MessageReceived;
private void MessageFromOtherObject_Received(object sender, EventArgs arg)
{
//do some work
}
public void StartListeningToObject(MyClass obj)
{
obj.MessageReceived += MessageFromOtherObject_Received;
}
public void StopListeningToObject(MyClass obj)
{
obj.MessageReceived -= MessageFromOtherObject_Received;
}
}
顺便说一句,别忘了触发那个事件!
你的代码被破坏的原因是因为你创建了这两个方法:
public void SubscribeToMessages(Action<object, EventArgs> eventHandler)
{
this.MessageReceived += new EventHandler<EventArgs>(eventHandler);
}
public void UnsubscribeFromMessages(Action<object, EventArgs> eventHandler)
{
this.MessageReceived -= new EventHandler<EventArgs>(eventHandler);
}
而不仅仅是来自事件的 adding/removing 处理程序(这是你应该做的)你实际上在做一些完全不同的事情。
SubscribeToMessages
正在添加一个事件处理程序,该事件处理程序在调用时将调用 eventHandler
委托的 Invoke
方法。
当您调用 UnsubscribeFromMessages
时,您试图删除处理程序,该处理程序的主体是对您已传递的 eventHandler
实例的 Invoke
方法的调用。但是,您将不同的 Action
实例传递给这两个方法调用中的每一个(即使这两个不同的操作都指向相同的 method/object 对),因此您尝试的事件处理程序add/remove 分别指代不同的 Action
个实例,因此不被视为相等。
如果您直接 add/remove 事件处理程序,而不是在第二层间接层中添加一个事件处理程序,该事件处理程序调用一个事件处理程序,该事件处理程序调用实际方法,您会没事的。
或者,您使用的 subscribe/unsubscribe 方法没有与事件不同的委托。让他们接受实际事件类型的代表,这样您就可以简单地 add/remove 他们,这也将删除额外的间接层。
问题在于,已注册的委托人的目标实际上是 eventHandler.Invoke
,而实际上并不是您要委托给的 target/method。然后,当您尝试删除处理程序时,它是针对新委托对象的 Invoke
方法的,因此它们不被视为不相等,并且原始注册仍然存在。你想委派给 MessageFromOtherObject_Received
。共有三个选项
- 直接在
Start
/StopListeningToObject
中做add/remove
- 将
UnsubscribeFrom
/SubscribeToMessages
的参数类型改为EventHandler<EventArgs>
通过
创建一个具有正确target/method的委托var handler = (EventHandler<EventArgs>)Delegate.CreateDelegate(typeof(EventHandler<EventArgs>), eventHandler.Target, eventHandler.Method); this.MessageReceived += handler;
使用
UnsubscribeFromMessages
中的类似代码删除处理程序。