当它来到窗口GUI控件时,我应该只使用BeginInvoke而不是Invoke吗?

时间:2012-02-01 07:12:16

标签: c# multithreading user-interface

我正在学习GUI Thread与Worker Thread的行为 所以我创建了一个类,它将从不同的线程更新GUI控件......

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("\n\n\n");

        Thread.CurrentThread.Name = "Parent Thread";
        label1.Text = "I am One";
        System.Diagnostics.Debug.WriteLine("[button1_Click] label1.Text :" + label1.Text);



        Thread _Thred = new Thread(FunctionCallBack);
        _Thred.Name = "Child Thread";
        _Thred.Start();
        _Thred.Join();

        label1.Text = "I am Three";
        System.Diagnostics.Debug.WriteLine("[button1_Click] label1.Text :" + label1.Text);

    }

    void FunctionCallBack()
    {
        MethodInvoker _Method = delegate()
        {
            label1.Text = "I am Two";
            System.Diagnostics.Debug.WriteLine("[FunctionCallBack] label1.Text :" + label1.Text);
        };


        System.Diagnostics.Debug.WriteLine("[FunctionCallBack] label1.BeginInvoke(_Method) : Executed");            
        label1.BeginInvoke(_Method);

        /*
        System.Diagnostics.Debug.WriteLine("[FunctionCallBack] label1.Invoke(_Method) : Executed");
        label1.Invoke(_Method);
        */
    }
}

当我点击Button时,我得到了这个输出

Output when I using BeginInvoke Method
-------------------------------------- 

[button1_Click] label1.Text :I am One
[FunctionCallBack] label1.BeginInvoke(_Method) : Executed
The thread 'Child Thread' (0xfb8) has exited with code 0 (0x0).
[button1_Click] label1.Text :I am Three
[FunctionCallBack] label1.Text :I am Two

我使用Invoke方法更改了我的代码,而不是调用BeginInvoke方法。

System.Diagnostics.Debug.WriteLine("[FunctionCallBack] label1.Invoke(_Method) : Executed");
label1.Invoke(_Method);

我得到低于输出和程序停止。

Output when I using Invoke Method 
----------------------------------

[button1_Click] label1.Text :I am One
[FunctionCallBack] label1.Invoke(_Method) : Executed

请告诉我,我现在面临的这种情况是dead lock吗? 如果您同意,我是否有机会再次使用Control.Invoke方法?
特别是,对于这种情况,我是否只有一次机会使用Control.BeginInvoke方法?

我们将不胜感激。

2 个答案:

答案 0 :(得分:3)

问题在于你的button1_Click方法。它在GUI线程上调用,它在_Thread.Join上阻塞。你应该删除它,而不是等待线程完成;这是在另一个线程上执行某些操作的整个想法。

第一种情况的原因是工作线程不等待GUI线程更新然后返回,以便GUI线程被解除阻塞。

对于第二种情况,工作线程等待GUI更新,但它不能,因为它在等待工作人员完成时被阻止。是的,这是一个死锁,但问题实际上是点击方法。

答案 1 :(得分:1)

@RichardSchneider回答了为什么你遇到了僵局。

线程很难做到,不要让它变得比必要的复杂。

  • 避免裸线程,使用ThreadPool或BackgroundWorker。
  • 通常使用Control.BeginInvoke(),但是当你经常调用它时,你可能会淹没GUI线程。使用Control.Invoke()来限制后台线程。此外,它有助于保持UI更新的顺序。