INTRODUÇÃO:
Muitas vezes, quando desenvolvemos ou usamos algum tipo de software, encontramos uma certa “demora” na execução de tarefas, pois quando o usuário executa algum formulário que processa muitas informações, esse formulário fica travado até que execute a tarefa e ainda impede que o usuário acesse outra parte do programa.
Para empresas ou
programadores que desejam vender seus softwares isso acaba sendo deselegante, o
usuário quer algo que atenda suas necessidades, seja rápido, e sempre esteja
disponível quando precisar.
Neste artigo você aprenderá como criar uma thread em paralelo usando o componente BackgroundWorker, assim quando o programa tiver que realizar alguma operação muito demorada a thread em segundo plano irá processar as informações e depois que concluir notificará a thread principal. Consequentemente o programa não ficará travado e será possível executar outras tarefas.
AGORA VAMOS COMEÇAR
Estarei utilizando o
C# Express para criar este projeto, então abra o C# e comece um novo projeto do
tipo WindowsApplication, dê um nome qualquer e depois clique
em OK.
Agora acione a
ToolBox e arraste para o Form1 os seguintes componentes: um DataGridView, um
Button, e o BackgroundWorker. Adicione também um segundo Form.
O próximo passo é entrar no código do Form1 e certificar que ele esteja utilizando os namespaces:
using System.Data e using System.Data.SqlClient, se não estiver você deve incluí-los.
O passo seguinte é
importar um banco de dados para o projeto, então se você já tem um banco de
dados, importe ele para o projeto, se não crie um novo. Nesta aplicação eu irei
utilizar um banco de dados que criei no SQl Server, assim vou aproveitar para
ensinar um macete que muita gente tem dúvida.
Depois que o banco
já tiver sido importado, volte para o código do Form1 e numa parte publica do
código declare uma variável do tipo DataSet e uma String de conexão.
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private DataSet ds; public string Conexao = "Data Source=.\\SQLEXPRESS;AttachDbFilename=" + Environment.CurrentDirectory + "\\AquiTem_DataBase.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"; /* Esta é dica que eu gostaria de mostrar, a string de conexão pega o banco de dados de dentro do diretório \bin\Debug, então não importa onde você jogue seu projeto a string de conexão irá pegar seu banco de dados. Logo depois do Environment.CurrentDirectory + , você deve colocar \\nome_do_banco.mdf, se seu banco estiver dentro do bin\Debug, agora se ele estiver dentro de outra pasta no diretório bin\Debug basta colocar \\nome_dapasta\\nome_do_banco.mdf;IntegratedSecurity=True;Connect Timeout=30... */ |
Se estiver retornando algum erro (na
executção do programa) de que não foi encontrado o banco de dados, pode ser que
a pasta padrão do projeto esteja configurada para bin\Release, se isso
acontecer é só ir no Solution Explorer-->clicar no nome do
projeto com o botão direito-->Properties-->Build e mudar para
bin\Debug.
Bom, continuando, entre no Events do backgroundWorker1, ele possuí 3 eventos escolha o DoWork, e coloque este código:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { SqlConnection conn = new SqlConnection(Conexao); // A variável conn é do tipo SqlConnection e tem como parâmetro a string de conexão. for (int i = 0; i < 30; i++) // Se este Loop for executado rapidamente aumente o número de loops. { SqlCommand cmd = new SqlCommand ("INSERT INTO Funcionario (CodFunc,Nome) VALUES (" + i + ",'Teste')",conn); /* O loop vai fazer o SqlCommand inserir 30 valores no banco de dados que nós importamos, o objetivo disso é mostrar uma operação que gasta muito tempo, e que enquanto ele está executando esta ação nesta thread em paralelo você pode chamar o Form2, porque o Form1 não esta travado. */ try { conn.Open(); cmd.ExecuteNonQuery(); }
catch (Exception ex) { MessageBox.Show("Erro" + ex.Message); }
finally { conn.Close(); } } } |
Obs: Não esqueça de trocar a sintaxe do SqlCommand, lembre-se que nós
estamos usando banco de dados diferentes, e outra coisa importante que eu ainda
não mencionei, nesta thread você não pode criar funções que carregam
interfaces, por exemplo: você não pode carregar os dados do banco e depois
preencher o DataGridView, isto é função da thread principal.
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { SqlConnection conn = new SqlConnection(Conexao); SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Funcionario", conn); ds = new DataSet(); da.Fill(ds); // Preencho o DataSet com o SqlDataAdapter dataGridView1.DataSource = ds.Tables[0]; // Agora é exibido no DataGridView as informações do banco }
|
Agora
que já colocamos os códigos nos eventos do backgroundWorker1 só falta
aciona-los, então no evento Load do Form1 coloque isto:
private void Form1_Load(object sender, EventArgs e) { backgroundWorker1.RunWorkerAsync(); // Quando o programa for executado a thread já será executada } |
Tudo o que falta é colocarmos o código do Button1, nele apenas colocaremos o código para chamar o Form2. Então ficará assim:
private void button1_Click(object sender, EventArgs e) { Form2 f = new Form2(); f.Show(); } |
Finalmente o programa está pronto agora vamos executá-lo, note que quando o Form1 é carregado ele está inserindo informações no banco de dados, normalmente ele ficaria travado até terminar de fazer isso, mas se você clicar no Button1 ele chamará o Form2 e continuará executando a ação sem interferir no desempenho do programa.
CONCLUSÃO:
Neste artigo foi criado um programa básico para demonstrar como uma thread pode aumentar o desempenho de um programa, quanto ao banco de dados é um assunto que é muito abordado na área de programação então não quis entrar em muitos detalhes, mas neste exemplo poderia ser usado um banco feito no Access.
Autor:
Geisson Pires da Silva
Técnico em Informática – Etec Pedro Ferreira Alves