2009-02-17 257 views
0

我面臨一個僵局,我的代碼結構與此類似:死鎖鎖()方法

private delegate void UpdateControlDelegate(string value); 

public void UpdateControl(string value) 
{ 
    if (txtAddress.InvokeRequired) 
    { 
     txtAddress.Invoke(new UpdateControlDelegate(UpdateControl), value); 
    } 
    else 
    { 
     txtAddress.Text = value; // This is in GroupBox1 
     txtValue.Text = value; // This is in GroupBox2 
    } 
} 

class ThreadHandler 
{ 
    List<string> _list = new List<string>(); 
    object _criticalSection = new object(); 

    public ThreadHandler() 
    { 
     new Thread(new ThreadStart(Run)).Start(); 
    } 

    public static ThreadHandler _threadHandler = null; 

    public static ThreadHandler GetThreadHandler() 
    { 
     if (_threadHandler == null) 
     { 
      _threadHandler = new ThreadHandler(); 
     } 

     return _threadHandler; 
    } 

    public void Run() 
    { 
     while (true) 
     { 
      // some code 

      lock (_criticalSection) 
      { 
       foreach (string str in _list) 
       { 
        // some Code 
       } 
      } 

      // some code 
      Thread.Sleep(SomeTime); 
     } 
    } 

    public void AddItem(string item) 
    { 
     lock (_criticalSection) 
     { 
      _list.Add(item); 
     } 
    } 

    public void RemoveItem(string item) 
    { 
     lock (_criticalSection) 
     { 
      _list.Remove(item); 
     } 
    } 

} 

但使用相同的代碼,我只是修改了UpdateControl方法是這樣的:

private delegate void UpdateControlDelegate(string value); 

public void UpdateControl(string value) 
{ 
    if (InvokeRequired) 
    { 
     BeginInvoke(new UpdateControlDelegate(UpdateControl), value); 
    } 
    else 
    { 
     txtAddress.Text = value; // This is in GroupBox1 
     txtValue.Text = value; // This is in GroupBox2 
    } 
} 

這工作正常。問題是什麼?

+0

我不知道如何發佈另一個問題在同一個頁面,所以我提出了我的詳細問題在另一個頁面中。以下給出以下列表 http:// stackover flow.com/questions/556883/deadlock-in-lock – Mohanavel 2009-02-17 13:54:15

回答

4

問題幾乎可以肯定的是,你正在後臺線程中獲取鎖,然後調用Control.Invoke,並調用嘗試獲取相同鎖的委託(在UI線程上)。它不能這樣做,因爲另一個線程持有鎖 - 並且在等待UI操作完成時將繼續保持鎖。

無可否認,在您發佈的UpdateControl方法中沒有鎖定,但我懷疑這不是完整的代碼 - 並且您沒有顯示您使用的地方AddItemRemoveItem

我注意到,GetThreadHandler()不是線程安全的,順便說一句 - 這看起來像我的錯誤...

0

你從主線程中調用的AddItem和removeItem而從主叫UpdateControl工作者線程?這將導致死鎖。

0

這裏是我的代碼,

public class ValueReader 
{ 
    List<IDataReader> _list = new List<IDataReader>(); 

    object _criticalSection = new object(); 

     public ValueReader() 
     { 
     //Nothign here 
     } 

     public void Attach(IDataReader reader) 
     { 
      lock(_criticalSection) 
      { 
       _list.Add(reader); 
      } 
     } 

     public void Detach(IDataReader reader) 
     { 
      lock(_criticalSection) 
      { 
       _list.Remove(reader); 
      } 
     } 

     public void Notify(string value) 
     { 
      lock(_criticalSection) 
      { 
       foreach(IDataReader reader in _list) 
       { 
        reader.Update(value); 
       } 
      } 
     } 

     public void Start() 
     { 
      new Thread(new ThreadStart(Run)).Start(); 
     } 


     private void Run() 
     { 
      while(true) 
      { 

       //generate value 
       Notify(value); 

       Thread.Sleep(5000); 

      } 
     } 

} 




public interface IDataReader 
{ 
    void UpdateControls(string value); 
} 

public class FirstClass : IDataReader 
{ 

    .... 
    ...... 
    ValueReader _reader = null; 

    public FirstClass() 
    { 

     _reader = new ValueReader(); 
       _reader.Start(); 
     _reader.Attach(this); 

    } 

    private void AddToSmartClient() 
    { 
     // _reader has added to SmartClient's WorkItem 
    } 


    private delegate void UpdateControlDelegate(string value); 

    public void UpdateControl(string value) 
    { 
     if(txtAddress.InvokeRequired) 
     { 
      txtAddress.Invoke(new UpdateControlDelegate(UpdateControl), value); 
     } 
     else 
     { 
      txtAddress.Text = value; 
      txtValue.Text = value; 
     } 
    } 

} 


public class SecondClass : IDataReader 
{ 
     .... 
    ...... 
    ValueReader _reader = null; 

    public void SecondClass() 
    { 
     _reader = ReadFromSmartClient(); 
     _reader.Attach(this); 
    } 

    private ValueReader ReadFromSmartClient() 
    { 
     reader = //Get from SmartClient's Workitem. 
     return reader 
    } 

    private delegate void UpdateControlDelegate(string value); 

    public void UpdateControl(string value) 
    { 
     if(InvokeRequired) 
     { 
      BeginInvoke(new UpdateControlDelegate(UpdateControl), value); 
     } 
     else 
     { 
      control1.Text = value; 
      control2.Text = value; 
     } 
    } 

} 

我只調用了一段時間的Firstclass。在這種情況下,它的工作正常。在我調用第二個類的時候,此時從第二個類調用Attach時,應用程序掛起(我注意到它直到Attach方法的鎖(_criticalSection)。)

經過一段時間我轉換了Update控件弗里斯特類如下

 public void UpdateControl(string value) 
{ 
    if(InvokeRequired) 
    { 
     BeginInvoke(new UpdateControlDelegate(UpdateControl), value); 
    } 
    else 
    { 
     txtAddress.Text = value; 
     txtValue.Text = value; 
    } 
} 

這是調用二等之後也運作良好。爲什麼它的發生?