2011-10-03 26 views
0

我有一個窗體上有一個控件來顯示一些自定義對象。在表單中,我訂閱了一個事件AddObject,它將對象添加到ToAdd列表中,因爲它們是從服務器進來的。我設置了一個計時器,每10秒鐘運行一次,以便將ToAdd列表中的對象複製到顯示列表中(當它們進入時,它們將大量項目添加到控件中的次數比1次更多),這些項目綁定到控制我的表單,然後清除ToAdd列表。在BeginInvoke內部鎖定安全嗎?有沒有更好的方法來做到這一點?在BeginInvoke調用中安裝lock()是否安全?

 private System.Threading.Timer aTimer; 
     private readonly Object sync = new Object(); 
     List<object> ToAdd = new List<object(); 
     List<object> Display = new List<object(); 

     private void Init() 
     { 
      TimerCallback tcb = IntermittentProcessMessages; 
      aTimer = new System.Threading.Timer(tcb, null, 1000, 100); 
      Server.MessageReceived += AddObject; 
     } 

     private void AddObject(object t) 
     { 
      lock (sync) 
      { 
       try 
       { 
        ToAdd.Add(t); 
       } 
       finally() {} 
      } 
     } 


     private void IntermittentProcessMessages(object source) 
     { 
      try 
      { 
       if (this.IsHandleCreated == false) 
       { 
        return; 
       } 
       this.BeginInvoke((Action)delegate() 
       { 
        lock (sync) 
        { 
         if (ToAdd.Count > 0) 
         { 
          ToAdd.ForEach(f => Display.Add(f)); 
          ToAdd.Clear(); 
         } 
        } 
       } 
      } 
      finally(){} 
    } 
+0

對我來說看起來很好。 – Gabe

+0

您在AddObject和BeginInvoke中使用相同的同步對象。使用兩個不同的同步對象,以便它們不會彼此阻塞。 –

+0

@UnmeshKondolikar,他們*應該*相互阻止,因爲他們保護'顯示'列表。 –

回答

1

是的,它是安全的。從技術上講,該鎖不在BeginInvoke中,但在從delegate創建的匿名函數中。

一些注意事項:

  • List<T>具有AddRange方法,該方法比多次Add更有效。
    使用它就像Display.AddRange(ToAdd);
  • 由於BeginInvoke立即返回,IntermittentProcessMessages中的代理不被try-catch覆蓋。
相關問題