Потокобезопасные обновления элемента управления WinForm из других классов - PullRequest
4 голосов
/ 10 января 2012

Может ли кто-нибудь помочь мне решить следующую проблему:

Существует два класса MainForm и LWriter.Ниже приведен метод от LWriter, который помимо записи в файл отправляет некоторые обновления элементу управления RichTextBox (через mainForm.UpdateLog (text)).Все работает нормально, однако, этот метод WriteOutput также выполняет некоторую обширную обработку, которая во время вычисления замораживает форму.

Я думаю, что WriteOutput должен быть заключен в отдельный потокМожет ли кто-нибудь помочь мне объяснить, как поместить WriteOutput (класс LWriter) в поток, который затем будет безопасно вызывать mainForm.UpdateLog () из mainFrom?

Я новичок в темах, поэтому помощь будет высоко ценится.

public void WriteOutput(string output, Links[] links)
{
   try {
      using (StreamWriter sw = new StreamWriter(output)) {
         for (int x= 1; x<links.Length;x++) {
       ...
           sw.WriteLine( ... );
           sw.Flush();                              
         }
         mainForm.UpdateLog(<text>);
      }
   } catch(Exception e) { ... }
}

Ответы [ 4 ]

6 голосов
/ 10 января 2012

Как правило, вы должны выполнять этот трудоемкий процесс в BackgroundWorker. Определите метод работы:

private void worker_DoWork(object sender, DoWorkEventArgs e)
{   
    // execute your WriteOutput method
}

и устанавливается как DoWork обработчик события:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync(); // start the worker

Чтобы безопасно обновить пользовательский интерфейс из другого потока, используйте метод Control.BeginInvoke:

mainForm.BeginInvoke(
   () => { mainForm.UpdateLog(<text>); });
3 голосов
/ 10 января 2012

delegate может использоваться для потоковых вызовов

Проверьте это http://msdn.microsoft.com/en-us/library/ms171728.aspx

            // This delegate enables asynchronous calls for setting
    // the text property on a TextBox control.
    delegate void SetTextCallback(string text);

    // This method demonstrates a pattern for making thread-safe
    // calls on a Windows Forms control. 
    //
    // If the calling thread is different from the thread that
    // created the TextBox control, this method creates a
    // SetTextCallback and calls itself asynchronously using the
    // Invoke method.
    //
    // If the calling thread is the same as the thread that created
    // the TextBox control, the Text property is set directly. 

    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the
        // calling thread to the thread ID of the creating thread.
        // If these threads are different, it returns true.
        if (this.textBox1.InvokeRequired)
        {   
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.textBox1.Text = text;
        }
    }
2 голосов
/ 25 октября 2013

Как предполагает Sonu, delegate можно использовать для вызовов с безопасным потоком, а вы можете использовать Linq для сокращения кода:

this.BeginInvoke( (Action) delegate ()
{
       //code to update UI
});

См. эту ссылку для получения дополнительной информации.

1 голос
/ 10 января 2012

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

Множество примеров этого в сети и переполнение стека.

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