.net 为多线程应用程序添加和删除事件处理程序

.net 为多线程应用程序添加和删除事件处理程序,.net,multithreading,event-handling,listener,.net,Multithreading,Event Handling,Listener,我有一个问题,如何在异步回调的多线程环境中正确地添加/删除事件处理程序 我有一个MyCore类,它从ProxyDLL接收异步回调,ProxyDLL从非托管代码发送回调。我有订阅活动的表单(托管) 从事件附加/分离的正确方法是什么。我注意到MulticastDelegate具有调用计数。它是干什么的?若回调调用正在进行中,直到回调完成,事件的内部逻辑是否会阻止从事件分离?那只小玫瑰的计数是否存在? 厌恶活动(通常)是安全的吗 类格式1 { 事件处理程序m_OnResponse; Int32 m_S

我有一个问题,如何在异步回调的多线程环境中正确地添加/删除事件处理程序

我有一个MyCore类,它从ProxyDLL接收异步回调,ProxyDLL从非托管代码发送回调。我有订阅活动的表单(托管)

从事件附加/分离的正确方法是什么。我注意到MulticastDelegate具有调用计数。它是干什么的?若回调调用正在进行中,直到回调完成,事件的内部逻辑是否会阻止从事件分离?那只小玫瑰的计数是否存在? 厌恶活动(通常)是安全的吗

类格式1
{
事件处理程序m_OnResponse;
Int32 m_SomeValue;
表格1()
{
m_OnResponse=neweventhandler(OnResponseImpl);
m_MyCore.SetCallBackOnLogOn(m_OnResponse);
}
~Form1()
{
m_MyCore.ReleaseCallBackOnLogOn(m_OnResponse);
}
私有OnResponseImpl(对象发送方,事件参数e)
{
线程。睡眠(60*1000);

m_SomeValue=1;//默认的事件添加和删除操作是。在大多数情况下,您不需要担心这一部分。您需要担心的是多播委托的调用

public void DoDispatchOnLogOn()
{
  EventHander local;
  lock (this)
  {
    local = OnLogOn;
  }
  if (local != null)
  {
    local(this, null);
  }
}
我在这里所做的是创建一个局部变量,该变量将保存
OnLogOn
委托链。我在这里利用多播委托的不变性,以便我们可以对null和调用序列进行线程安全检查。
lock
仅用于确保“刷新”读取
OnLogon
,如果您不介意读取“过时”的内容,则它是严格可选的

更新:

我需要确保在调用时不会调用回调 ReleaseCallBackOnLogOn已结束取消订阅委托

在大多数情况下,我的代码不会尝试执行任何已取消订阅的事件处理程序。在删除事件处理程序和引发事件之间存在轻微的竞争,这可能导致事件处理程序被执行,即使它最近刚刚被删除

我需要确保我的类实例仍然处于活动状态,直到调用 回调已完全完成

委托持有对包含目标方法的类实例的引用。这将使您的实例保持根目录,因此不符合垃圾收集的条件。您无需担心这一点


我应该指出,
~Form1
终结器不是删除事件处理程序的好地方。请记住,委托持有对包含目标方法的实例的引用,因此在大多数情况下,终结器不会被调用,事件处理程序也不会从事件中删除。

谢谢!这是一个好地方。关于安全性ty-你想说从事件中取消订阅侦听器是一个阻塞调用吗?@adspx5:C#4.0和更高版本使用
互锁。比较exchange
进行订阅和取消订阅。C#3.0和更低版本使用
锁(此)
。因此,如果锁当前由其他人持有,C#3.0及更低版本将被阻止。这不是我想要理解的。我理解,但不担心调用列表的更改。我担心委托的生存期。我需要确保在ReleaseCallBackOnLogOn结束取消订阅委托时不会调用回调。猜是这样的我的委托睡眠10秒,然后更改MyForm::m_Somevalue。我需要确保我的类实例仍然处于活动状态,直到回调调用完全完成。谢谢!已将它们移动到OnDispose()