когда дело доходит до управления графическим интерфейсом окна, я должен использовать только BeginInvoke, а не Invoke? - PullRequest
0 голосов
/ 01 февраля 2012

Я изучаю поведение потока GUI против рабочего потока.
Поэтому я создаю класс, который будет обновлять GUI Control из другого потока ...

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);
        */
    }
}

Когда я нажимаю кнопку, я получаю этот вывод

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 ]

3 голосов
/ 01 февраля 2012

Проблема связана с вашим методом button1_Click. Он вызывается в потоке графического интерфейса и блокируется в _Thread.Join. Вы должны удалить это и не ждать окончания потока; в этом вся идея выполнения чего-либо в другом потоке.

Причина, по которой работает первый случай, заключается в том, что рабочий поток не ждет обновления потока GUI, а затем возвращается, так что поток GUI затем разблокируется.

Во втором случае рабочий поток ожидает обновления графического интерфейса, что невозможно, поскольку он заблокирован в ожидании завершения рабочего процесса. Да, это мертвая блокировка, но проблема действительно в методе щелчка.

1 голос
/ 01 февраля 2012

@ RichardSchneider ответил, почему у вас тупик.

Потоки трудно понять правильно, не усложняйте их, чем нужно.

  • Избегайте использования чистых потоков, используйте ThreadPool или BackgroundWorker.
  • Обычноиспользуйте Control.BeginInvoke (), но когда вы вызываете его слишком часто, вы можете забить поток GUI.используйте Control.Invoke () для регулирования фонового потока.Также это помогает поддерживать порядок обновления пользовательского интерфейса.
...