2009-02-17 210 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; 
    } 
} 

这是调用二等之后也运作良好。为什么它的发生?