我有一个问题如何正确地在多线程环境中添加/删除事件处理程序异步回调。添加和删除事件处理程序为多线程应用
我有MyCore类从ProxyDLL接收异步回调其从非托管代码调度回调。我有表单(托管),其中订阅了事件。
什么将安装/从事件剥离正确的方法。我注意到MulticastDelegate有_invocationcount。它能做什么?如果回调调用正在进行,直到回调完成,事件的内部逻辑是否阻止与事件分离?该puprose是否存在_invocationcount? 从事件(一般来说)是detathing是踩踏?
class Form1
{
EventHandler m_OnResponse;
Int32 m_SomeValue;
Form1()
{
m_OnResponse = new EventHandler(OnResponseImpl);
m_MyCore.SetCallBackOnLogOn(m_OnResponse);
}
~Form1()
{
m_MyCore.ReleaseCallBackOnLogOn(m_OnResponse);
}
private OnResponseImpl(object sender, EventArgs e)
{
Thread.Sleep(60*1000);
m_SomeValue = 1; // <<-- How to/Who guarantees that Form1 obj is still
// alive. May be callback was invoked earlier and
// we just slept too long
if (!this.IsDisposed)
{
invokeOnFormThread(DoOnResponseImpl, sender, e);
}
}
}
class MyCore
{
private event EventHandler OnLogOn;
public void SetCallBackOnLogOn(EventHandler fn)
{
// lock (OnLogOn)
{
OnLogOn += fn;
}
}
ReleaseCallBackOnLogOn(EventHandler fn)
{
// lock (OnLogOn)
{
OnLogOn -= fn;
}
}
public void DoDispatchOnLogOn()
{
// lock (OnLogOn)
{
if (OnLogOn != null)
{
OnLogOn(this, null);
}
}
}
}
谢谢!这是一个很好的观点。关于安全性 - 你想说从退出事件中取消订阅监听器是一个阻塞呼叫吗? – adspx5 2012-04-17 18:52:53
@ adspx5:C#4.0和更高版本使用'Interlocked.CompareExchange'做注册和取消。 C#3.0及更低版本使用'lock(this)'。因此,如果锁定当前由其他人持有,C#3.0及更低版本将会阻止。 – 2012-04-17 19:39:59
这不完全是我想了解的。我明白了,但不用担心调用列表的变化。我担心我的代表一生。我需要确保在ReleaseCallBackOnLogOn结束取消订阅委托时不会调用回调。猜猜我的委托人睡了10秒,然后改变了MyForm :: m_Somevalue。我需要确保我的类实例仍然存在,直到完成调用回调。 – adspx5 2012-04-17 20:47:00