Trabalhando com BackGroundWorker
Olá pessoal. Muitas vezes quando desenvolvemos algum aplicativo Windows, e chamamos algum processamento que demore para ser executado, a interface espera que esse processamento termine, essa espera impossibilita o usuário de interagir com ela. Essa impossibilidade gera um desconforto para o usuário, fazendo com que ele ache que o sistema é lento ou ruim.
Com o Microsoft .Net Framework, podemos utilizar o recurso de Multithreading, e nosso aplicativo pode invocar a execução de uma threading (principal) enquanto outra já está em execução. Essa threading principal poderá ser utilizada pelo usuário, sem que a outra threading interfira nela. Essa nova threading poderá notificar o andamento bem como a finalização do processamento.
O Microsoft .Net Framework 2.0 nos traz um componente que encapsula a criação de threads e passa a expor a sua notificação e manipulação através de seus métodos e eventos. O nome desse componente é “BackGroundWorker”. Ele é responsável por controlar toda a infra-estrutura necessária para criar e controlar uma nova thread.
Bom pessoal, vamos iniciar a parte prática. Abra o nosso Visual Studio 2005 em qualquer uma das versões (dica: vá em iniciar > executar e digite devenv e aperte o enter. Isso abrirá o Visual Studio)
Irei colocar a listagem de códigos em VB.Net e C#.
Crie um novo projeto de Windows Application. Para o exemplo em VB.Net irei nomear o meu de “Artigo_BackGroundWorker_vb “, e para o exemplo em C# irei nomear o meu de “Artigo_BackGroundWorker_cs”.
Abra o arquivo Form1.vb e adicione um GridViews, dois Botões e um BackgroundWorker (esse controle você encontrará na toolbox dentro de Components).
Listagem 1.1 (Propriedades alteradas dos controles)
Botões:
Name: btnCarregarGrid
Text: CarregarGrid
Name: btnTestarThreading
Text: Testar Threading
DataGridView
Name: dgvTeste
BackgroundWorker
Name: bwrTeste
Organize seus itens para que fiquem dessa maneira:
Agora clique em ViewCode ou aperte a tecla F7 de seu teclado. Dentro da classe Form1, adicione a variável MeuDataTable do tipo DataTable.
Em seguida crie um procedimento privado nomeando-o de “PopularDataTable” (listagem 1.2 vb ou 1.2 cs)
Listagem 1.2 vb
Private Sub PopularDataTable()
Try
'*********************************************************
'Iremos forçar que o nosso aplicativo demore
'alguns segundos, especificaremos isso na
'Threading atual, conforme a linha de código abaixo
'*********************************************************
System.Threading.Thread.Sleep(3000)
Dim intCont As Integer
'*********************************************************
'A estrutura de repetição seguir, servirá para
'adicionarmos itens ao nosso DataTable
'*********************************************************
For intCont = 0 To 2000
Dim dr As Data.DataRow
'********************************************************
' Verificando se a quantidade de coluna no datatable
' é menor que 1, sendo será criada um coluna e adicionada
' ao dataTable
'********************************************************
If MeuDataTable.Columns.Count < 1 Then
Dim dc As New Data.DataColumn
dc.ColumnName = "id"
MeuDataTable.Columns.Add(dc)
End If
'********************************************************
' Criando uma nova Linha para o nosso datetable
'********************************************************
dr = MeuDataTable.NewRow()
'********************************************************
' Atribuindo um valor a primeira coluna dessa nova linha
'********************************************************
dr(0) = intCont * 2000
'********************************************************
' Adicionando o linha ao DataTable
'********************************************************
MeuDataTable.Rows.Add(dr)
Next
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
End Sub
Listagem 1.2 cs
private void PopularDataTable()
{
try
{
/*********************************************************
'Iremos forçar que o nosso aplicativo demore
'alguns segundos, especificaremos isso na
'Threading atual, conforme a linha de código abaixo
'********************************************************/
System.Threading.Thread.Sleep(3000);
int intCont;
/*********************************************************
'A estrutura de repetição seguir, servirá para
'adicionarmos itens ao nosso DataTable
'********************************************************/
for (intCont = 0; intCont <= 2000; intCont++)
{
DataRow dr;
/********************************************************
' Verificando se a quantidade de coluna no datatable
' é menor que 1, sendo será criada um coluna e adicionada
' ao dataTable
'*******************************************************/
if (this.MeuDataTable.Columns.Count < 1)
{
DataColumn dc = new DataColumn();
dc.ColumnName = "id";
this.MeuDataTable.Columns.Add(dc);
}
/********************************************************
' Criando uma nova Linha para o nosso datetable
'*******************************************************/
dr = this.MeuDataTable.NewRow();
dr[0] = intCont;
/********************************************************
' Adicionando o linha ao DataTable
'*******************************************************/
this.MeuDataTable.Rows.Add(dr);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
Agora iremos codificar o evento DoWork do componente BackgroundWorker. Esse evento será o responsável por executar os procedimentos em um nova thread. Acompanhe na listagem 1.3 vb ou 1.3 cs.
Listagem 1.3 vb
Private Sub bwrTeste_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwrTeste.DoWork
Try
Me.PopularDataTable()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Listagem 1.3 cs
Private void bwrTeste_DoWork(object sender, DoWorkEventArgs e)
{
try
{
this.PopularDataTable();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Agora iremos codificar o evento RunWorkerCompleted do componente BackgroundWorker. Esse evento só é disparado quando é finalizada a thread criada no evento DoWork. Acompanhe na listagem 1.4 vb ou 1.4 cs.
Listagem 1.4 vb
Private Sub bwrTeste_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bwrTeste.RunWorkerCompleted
Try
Me.dgvTeste.DataSource = MeuDataTable
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Listagem 1.4 cs
private void bwrTeste_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
try
{
this.dgvTeste.DataSource = this.MeuDataTable;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Agora vamos codificar o evento Click do botão btnCarregarGrid. Nesse evento iremos dizer ao aplicativo que ele deverá iniciar o BackgroundWorker, fazendo com que dispare o evento DoWork do componente BackgroundWorker. Acompanhe na listagem a.5 vb ou 1.5 cs.
Listagem 1.5 vb
Private Sub btnCarregarGrid_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCarregarGrid.Click
Try
Me.bwrTeste.RunWorkerAsync()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Listagem 1.5 cs
private void btnCarregarGrid_Click(object sender, EventArgs e)
{
try
{
this.bwrTeste.RunWorkerAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Codifique o evento Click do botão btnTestarThreading. O objetivo desse evento nesse contexto é apenas mostrar que mesmo o aplicativo carregando o grid, você poderá deixar outra funcionalidades livres. Acompanhe na listagem 1.6 vb ou 1.6 cs.
Listagem 1.6 vb
Private Sub btnTestarThreading_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTestarThreading.Click
Try
MessageBox.Show("Funcionando!!!!")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Listagem 1.6 cs
private void btnTestarThreading_Click(object sender, EventArgs e)
{
try
{
MessageBox.Show("Funcionando!!!!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Bom pessoal, por enquanto é isso. Fiquem a vontade para fazer críticas e sugestões. Abraço!