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
    }
}

これはうまくいっています。何が問題ですか?

4

3 に答える 3

4

問題はほぼ確実に、バックグラウンド スレッド内でロックを取得してControl.Invokeから を呼び出し、同じロックを取得しようとする (UI スレッドで) デリゲートを呼び出すことです。他のスレッドがロックを保持しているため、これを行うことはできません。UI 操作が完了するまでロックを保持し続けます。

確かに、投稿した UpdateControl メソッド内にロックはありませんが、それは完全なコードではないと思われAddItemますRemoveItem

ちなみに、 GetThreadHandler() はスレッドセーフではないことに注意してください-それは私にはバグのように見えます...

于 2009-02-17T12:43:41.507 に答える
0

ワーカー スレッドから UpdateControl を呼び出しながら、メイン スレッドから AddItem と RemoveItem を呼び出していますか? それはデッドロックを引き起こします。

于 2009-02-17T12:47:19.330 に答える