C# - Atualizando a Interface a partir de outra thread - II


Neste artigo veremos como atualizar os elementos da interface no Windows Forms a partir de outra thread.

Continuando a primeira parte do artigo verermos agora um exemplo usando o manipulador de eventos BackGroundWorker.


Usando o BackGroundWorker

Uma maneira fácil de implementar multithreading é com o componente System.ComponentModel.BackgroundWorker , que usa um modelo orientado a eventos.

Nesta abordagem, a thread de segundo plano executa o evento BackgroundWorker.DoWork, que não interage com a thread principal.

A thread principal executa os manipuladores de eventos BackgroundWorker.ProgressChanged e BackgroundWorker.RunWorkerCompleted, que podem chamar os controles da thread principal.

Para fazer uma chamada de thread-safe usando BackgroundWorker, vamos criar um método na thread de segundo plano para executar o trabalho e vincular esse método ao evento DoWork.

Depois vamos criar outro método na thread principal para relatar os resultados do trabalho em segundo plano e vincular o método ao evento ProgressChanged ou RunWorkerCompleted. Para iniciar a thread em segundo plano, chamamos BackgroundWorker.RunWorkerAsync.

Temos um projeto Windows Forms onde no formulário Form1.cs incluimos um controle TextBox e um controle Button.

Neste exemplo usamos o manipulador de eventos RunWorkerCompleted para definir a propriedade Text do controle TextBox.

using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace WF_BackGroundWorker1
{
    public partial class Form1 : Form
    {
        private BackgroundWorker backgroundWorker1;
        public Form1()
        {
            InitializeComponent();
            backgroundWorker1 = new BackgroundWorker();
            backgroundWorker1.DoWork +=
                new DoWorkEventHandler(BackgroundWorker1_DoWork);
            backgroundWorker1.RunWorkerCompleted +=
                new RunWorkerCompletedEventHandler(BackgroundWorker1_RunWorkerCompleted);
        }
        private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }

        private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            // Da um delay de 2 segundos para emular a obtenção dos dados
            System.Threading.Thread.Sleep(2000);
            e.Result = "Este definido de forma segura com BackgroundWorker.";
        }
        private void BackgroundWorker1_RunWorkerCompleted(
            object sender, RunWorkerCompletedEventArgs e)
        {
            textBox1.Text = e.Result.ToString();
        }
    }
}

Executando este código teremos a execução da operação em outra thread.

Assim, vimos que podemos usar a classe BackgroundWorker para executar uma operação em uma thread separada.

Pegue o projeto aqui: WF_ThreadSegura2.zip

"Vós me chamais Mestre e Senhor, e dizeis bem, porque eu o sou.
Ora, se eu, Senhor e Mestre, vos lavei os pés, vós deveis também lavar os pés uns aos outros.
Porque eu vos dei o exemplo, para que, como eu vos fiz, façais vós também."
João 13:13-15

Referências:


José Carlos Macoratti