我有一個問題如何正確地在多線程環境中添加/刪除事件處理程序異步回調。添加和刪除事件處理程序爲多線程應用
我有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