2016-06-12 72 views
0

我正在編寫的類正在使用多線程,並且我已爲此類創建了此擴展方法以便以線程安全方式提出事件。在引發線程事件時無法訪問已處理的對象

static class MultiThreadHelper 
{ 
    public static object Raise(this MulticastDelegate eventToRaise, object sender, EventArgs e) 
    { 
     object retVal = null; 

     MulticastDelegate threadSafeMulticastDelegate = eventToRaise; 
     if (threadSafeMulticastDelegate != null) 
     { 
      foreach (Delegate d in threadSafeMulticastDelegate.GetInvocationList()) 
      { 
       var synchronizeInvoke = d.Target as ISynchronizeInvoke; 
       if ((synchronizeInvoke != null) && synchronizeInvoke.InvokeRequired) 
       { 
        retVal = synchronizeInvoke.EndInvoke(synchronizeInvoke.BeginInvoke(d, new[] { sender, e })); 
       } 
       else 
       { 
        retVal = d.DynamicInvoke(new[] { sender, e }); 
       } 
      } 
     } 

     //Return the value of the event invocation or null if none. 
     return retVal; 
    } 
} 

當我的形式,試圖關閉一個揮之不去的線程仍在試圖向警方報到,並提出不再有處理程序的事件。

我最終得到下面的錯誤...

enter image description here

發生該行錯誤之前,我可以運行什麼樣的檢查?還有什麼我可以做的或者我可以採取不同的方法來解決這個問題?

回答

2

我的第一個想法是ManifestBuilder在關閉時並未退出委託。確保您使用-=語法取消訂閱。

+0

我在ManifestBuilder的FormClosing事件中這樣做。但是我將它作爲事件塊中的最後一個動作。當我把它作爲事件塊中的第一個動作時,似乎提升了這個問題。我認爲我的錯誤是讓用戶在我處理類對象之前取消訂閱......雖然我不明白爲什麼這會起作用。 –

+0

挖掘更多...在FormClosing事件中,我會嘗試調用將創建一個新線程的類的方法。然後,只要創建新的線程,我會退訂。然後......一旦線程完成,它會發送一個事件(認爲有一個訂閱)。在處理多線程時,有沒有辦法檢查任何訂閱是否還活着?我的問題很簡單,訂閱事件 - >強制線程在定時器上發送事件 - >取消訂閱 - >事件觸發認爲有訂閱但沒有訂閱去。 –

+0

在進一步檢查您的代碼時,我會查看您獲取對傳入您的Raise方法的eventToRaise引用的位置。我能想到的唯一的事情就是你在表單處理之前的某個時間點分配了這個變量,並且取消訂閱了事件,然後在表單被處理後使用它。 –

相關問題