2014-03-02 123 views
0

我想知道這種方法是否有潛在的僵局。在Timer Tick事件中使用「鎖定」是否死鎖安全?

示例代碼:當您單擊應用程序按鈕時,將創建一個Job對象並將其添加到作業列表中。添加代碼受'鎖定'保護。然後在計時器滴答事件中,我想從列表中刪除已完成的作業 - 鎖定計時器事件中的列表。

所以問題是,如果用戶按下「添加作業」按鈕,而計時器事件鎖定正在使用,這個應用程序會死鎖嗎?

計時器是一個Windows窗體計時器。

public partial class Form1 : Form 
{ 
    object listLock = new object(); 
    List<Job> jobsList = new List<Job>(); 
    public Form1() 
    { 
     InitializeComponent(); 
     timer1.Start(); 
    } 

    private void timer1_Tick(object sender, EventArgs e) 
    { 
     Job aJob; 
     lock(listLock) 
     { 
      for (int i = jobsList.Count - 1; i > -1; i--) 
      { 
       aJob = jobsList[i]; 
       if (aJob.IsCompleted) 
       { 
        jobsList.RemoveAt(i); 
       } 

      } 
     } 

    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     lock (listLock) 
     { 
      Job aJob = new Job(); 
      jobsList.Add(aJob); 
     } 

    } 
} 

//===================================== 
    class Job 
    { 
     bool isCompleted = false; 

     public bool IsCompleted 
     { 
      get { return isCompleted; } 
      set { isCompleted = value; } 
     } 

     public Job() 
     { 
      // do some work then mark complete 
      IsCompleted = true; 
     } 
} 

回答

2

計時器事件(來自Windows窗體計時器)從主消息循環中調度。所以他們將永遠不會與任何其他UI事件的處理程序重疊。

按下按鈕將進入消息隊列,並在定時器Tick處理程序完成後進行處理。 (因此,對於只由UI事件處理程序操作的數據結構,您不需要鎖定,因爲它們將按照它們排隊的順序依次運行)

+0

好的,謝謝你。那麼如果另一個Windows窗體在這個窗體上調用一個公共方法來添加一個項目到這個列表呢?這仍然是死鎖安全嗎? –

+1

@LTDan:只要它們是從單個消息循環('Main'方法中的'Application.Run')控制的,那麼它們共享一個隊列並按順序運行,沒有競爭條件。只有從另一個線程訪問數據結構時,纔會出現數據衝突。 –