C # - не удается добавить текст для управления из фоновых потоков с помощью Invoke () - PullRequest
1 голос
/ 16 мая 2011

Привет, у меня проблема с вызовом richTextBox из рабочего потока в C #.Я использую метод InvokeRequired / Invoke.Пожалуйста, смотрите мой код:

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

    private void ThreadSafe(MethodInvoker method)
    {
        if (InvokeRequired)
            Invoke(method);
        else
            method();
    }

    private void WorkerThread(object data)
    {
        string msg = "\nhello, i am thread " + data.ToString();
        ThreadSafe(delegate
        {
            richTextBox1.AppendText(msg);
        });
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Thread[] workers = new Thread[3];

        for (int i = 0; i < 3; i++)
        {
            workers[i] = new Thread(WorkerThread);
            workers[i].Start(i);
            string msg = "\nthread " + i.ToString() + "started!";
            richTextBox1.AppendText(msg);
        }

        int j = 3;
        while (j > 0)
        {
            for (int i = 0; i < 3; i++)
            {
                Thread.Sleep(250);
                richTextBox1.AppendText("\nChecking thread");
                if (workers[i].Join(250))
                {
                    string msg = "\nWorker thread " + i.ToString() + " finished.";
                    richTextBox1.AppendText(msg);
                    workers[i] = null;
                    j--;    // decrement the thread watch count
                }
            }
        }
    }
}

В поле расширенного текста печатается следующее:

thread 0started!
thread 1started!
thread 2started!
Checking thread
Checking thread
Checking thread
Checking thread
....

Это продолжается и продолжается, сообщение "привет" не печатается,и пользовательский интерфейс заморожен.Затем я изменил Invoke () на BeginInvoke (), но я знаю, что не должен этого делать, тогда результат будет таким:

thread 0started!
thread 1started!
thread 2started!
Checking thread
Worker thread 0 finished.
Checking thread
Worker thread 1 finished.
Checking thread
Worker thread 2 finished.
hello, i am thread 0
hello, i am thread 1
hello, i am thread 2

В чем причина и что мне делать?

Спасибо заранее.

Ответы [ 3 ]

5 голосов
/ 16 мая 2011

Метод Invoke запускает ваш делегат синхронно & mdash; он ожидает, пока поток пользовательского интерфейса фактически не выполнит его, прежде чем вернуть управление вызывающей стороне.
Поскольку поток пользовательского интерфейса ожидает завершения ваших потоков, вы получаете тупик.

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

1 голос
/ 16 мая 2011

Вы ждете завершения рабочих потоков, прежде чем покинуть ваш метод button1_Click.Это проблема, потому что ваши потоки не могут завершиться, пока они не смогут запустить делегат, который вызывает метод AppendText в том же потоке.

Когда вы переходите на BeginInvoke, у вас больше нет этой проблемы, потому что ваши рабочие потоки не блокируют ожидание делегата, который вызывает метод AppendText.

Если вы пытается заблокировать поток пользовательского интерфейса до тех пор, пока рабочие потоки не завершатся, вы просто не сможете, пока они полагаются на вызов Invoke.

0 голосов
/ 16 мая 2011

Вы не можете обновить элементы управления пользовательского интерфейса из другого потока, вот ответ

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...