.NET

29 mai, 2007

Trabalhando com BackgroundWorker

Publicidade

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!