Programação assíncrona é um assunto bastante completo e complexo. Um dos motivos para ser assim é que existem diversas formas para se executar código assincronamente, isto é, em uma thread separada. As principais estratégias são:
Usar a classe Thread;
Usar o componente BackgroundWorker;
Usar delegates;
Neste artigo vou falar da forma mais rápida de se executar um trecho de código em um thread separada e dedicada: através de delegates.
Existem três estratégias para executar código em uma thread dedicada, são eles:
Chame o método assíncronamente, faça alguma coisa e finalize a chamada assíncrona (a thread fica bloqueada até a o término da operação)
Chame o método assíncronamente, e enquanto a execução não terminar faça alguma coisa, e então finalize a chamada assíncrona.
Chame o método assínconamente, defina um CallBack para ser invocado no final da operação assíncorna, na implementação do CallBack finalize a chamada assíncrona.
A primeira coisa a se fazer é criar um delegate com a mesma assinatura do método que contém o código que se deseja executar assincronamente. Veja o exemplo:
Método:
public string BuscaDocumento(string autor, int posicao)
{
string caminho = string.Empty;
// faz alguma coisa
return caminho;
}
Delegate:
public delegate string BuscaDocumentoDelegate(string autor, int posicao);
Neste ponto já podemos realizar duas das estratégias de programação assíncrona usando delegates:
Chame o método assíncronamente, faça alguma coisa e finalize a chamada assíncrona (a thread fica bloqueada até a o término da operação)
Chame o método assíncronamente, e enquanto a execução não terminar faça alguma coisa, e então finalize a chamada assíncrona.
Vamos aos usos:
Caso 01: Chame o método assíncronamente, faça alguma coisa e finalize a chamada assíncrona (a thread fica bloqueada até a o término da operação)
BuscaDocumentoDelegate buscaDel = BuscaDocumento;
IAsyncResult result = buscaDel.BeginInvoke("Erico Veríssimo", 25, null, null);
//faça alguma coisa outra coisa
string resultado = buscaDel.EndInvoke(result); /* a thread bloqueia nesse ponto até que a operação BuscaDocumento seja concluida */
obs:
Os dois parâmetros nulos na chamada do método BeginInvoke são CallBack e State, respectivamente. Estes são necessários apenas para a terceira estratégia, a qual será demonstrada ainda neste artigo.
Caso 02: Chame o método assíncronamente, e enquanto a execução não terminar faça alguma coisa, e então finalize a chamada assíncrona.
BuscaDocumentoDelegate buscaDel = BuscaDocumento;
IAsyncResult result = buscaDel.BeginInvoke("Erico Veríssimo", 25, null, null);
while (!result.IsCompleted)
{
//faça qualquer coisa
}
string resultado = buscaDel.EndInvoke(result);
A vantagem desta implementação em relação às demais é que a thread principal não ficará bloqueada enquanto a thread em backgound não for concluída, o que permite que trechos de código sejam executados até a finalização da operação inciada via delegate.
A terceira forma é através de CallBacks, esta exige a implementação de outro método e será explicada a seguir.
Além do método com o código e do delegate equivalente é necessário um método de CallBack, que será invocado quando a operação assíncrona for concluída. O CallBack deve retornar void e receber um IasyncResult como argumento.
Método de CallBack:
public void BuscaDocumentoCallBack(IAsyncResult resultado)
{
BuscaDocumentoDelegate buscaDel = (BuscaDocumentoDelegate) resultado.AsyncState ;
string resultadoDaBusca = buscaDel.EndInvoke(resultado);
Console.WriteLine("Resultado da Busca: {0}", resultadoDaBusca);
}
Usando o delegate:
BuscaDocumentoDelegate buscaDel = BuscaDocumento;
buscaDel.BeginInvoke("Arnaldo Jabor", 34, BuscaDocumentoCallBack, buscaDel);
/* O fluxo desta thread continua, de modo que outras operações podem ser realizadas enquanto a operação em background prossegue, e quando esta finalizar o método BuscaDocumentoCallBack será invocado. */
Como podem ver não tem segredo. Essas técnicas são muito úteis em programas Windows Forms, pois nestes geralmente o usuário precisa de executar várias operações ao mesmo tempo, e além disso também são útis para processamentos longos que não necessitam de retorno imediato.
Em breve volto com Threads e BackgroundWorker!
Abraços,
Até
1 comentários:
Qual é a diferença de fazer assim e usar um objeto Thread?
Postar um comentário