PagSeguro
Canais iMasters

C# + Desenvolvimento + .NET

Recebendo retornos de threads em C#

Como mostrei no artigo anterior, todo programa desenvolvido em C# possui uma thread principal e podemos desenvolver outras threads para serem executadas em segundo plano. Podemos também chamar Threads passando parâmetros para elas. Além da passagem de dados para a Thread, existem situações em que é necessário retornar informações quando a execução da thread estiver concluída.

Para recuperar dados da thread, devemos criar um método que aceita os resultados de retorno como parâmetro. Em seguida, devemos criar um delegate para esse método. O construtor da classe deve aceitar um delegate que representa o método call-back. Antes que a thread esteja concluída, ela chama o delegate de retorno.

O código a seguir é uma calculadora simples, na qual a operação é executada através de uma thread em segundo plano, e o resultado é retornado para a thread principal, para ser mostrado para o usuário. No interior deste código estão os comentários explicando cada bloco.

// C#
class Program
{
static void Main(string[] args)
{
// Recebendo entradas do usuário
Console.WriteLine();
Console.Write(\"Informe o primeiro valor: \");
double d1 = Convert.ToDouble(Console.ReadLine());

Console.WriteLine();
Console.Write(\"Informe o segundo valor: \");
double d2 = Convert.ToDouble(Console.ReadLine());

Console.WriteLine();
Console.WriteLine(\"OPERAÇÕES\");
Console.WriteLine(\"1 - Soma\");
Console.WriteLine(\"2 - Subtração\");
Console.WriteLine(\"3 - Multiplicação\");
Console.WriteLine(\"4 - Divisão\");
Console.Write(\"Informe a operação desejada: \");
Operacao op =
(Operacao)Convert.ToInt32(Console.ReadLine());

// Instância da classe Calculadora
Calculadora calc = new
Calculadora(d1, d2, op,
new ResultDelegate(ResultCallback));

// Criando a thread
System.Threading.ThreadStart ts = new
System.Threading.ThreadStart(calc.Calcular);
System.Threading.Thread t = new
System.Threading.Thread(ts);

// Iniciando a execução da thread
t.Start();

Console.WriteLine();
Console.WriteLine(\"Thread principal em execução.\");
t.Join();
Console.WriteLine();
Console.WriteLine(\"Processamento concluído.\");
Console.ReadKey();
}

// Método executado pelo delegate
public static void ResultCallback(double valor)
{
Console.WriteLine(\"Valor Retornado da Calculadora: {0}\",
valor);
}
}

public class Calculadora
{
// Valores utilizados durante o cálculo.
private double valor1;
private double valor2;
private Operacao operacao;

// Delegate usado para executar o método de
// call-back quando a thread estiver completa
private ResultDelegate callback;

// O construtor obtendo os parâmetros
public Calculadora(double _valor1,
double _valor2,
Operacao _operacao,
ResultDelegate _callback)
{
this.valor1 = _valor1;
this.valor2 = _valor2;
this.operacao = _operacao;
callback = _callback;
}

public void Calcular()
{
double valorResultado;

if (this.operacao == Operacao.Soma)
valorResultado = this.valor1 + this.valor2;
else if (this.operacao == Operacao.Subtracao)
valorResultado = this.valor1 - this.valor2;
else if (this.operacao == Operacao.Multiplicacao)
valorResultado = this.valor1 * this.valor2;
else if (this.operacao == Operacao.Divisao)
valorResultado = this.valor1 / this.valor2;
else
valorResultado = 0;

if (callback != null)
callback(valorResultado);
}
}

// Delegate que define a assinatura
// para o método de callback.
public delegate void ResultDelegate(double valor);

// Enumerador de operações
public enum Operacao
{
Soma = 1,
Subtracao = 2,
Multiplicacao = 3,
Divisao = 4
}

O resultado dessa execução deverá ser algo como mostra a imagem abaixo:

\"Resultado

Nota: Fique sempre atento para a ocorrência de deadlocks. Sempre que necessário, utilize locks nos locais onde a concorrência pode ser grande e causar deadlocks. Isso é assunto para um outro artigo, mas, por enquanto, se quiser saber mais sobre isso, veja este link.

Código fonte

Os códigos fontes podem ser baixados aqui.

Referências 


Comente também

4 Comentários

Bruno
Bruno

Excelente exemplo, parabéns!

Bruno Pereira
Bruno Pereira

Legal o artigo. Obrigado por compartilhar. Não esqueça do artigo sobre deadlocks, por favor. Esse assunto de Thread em C# tá em falta aqui no Imasters.

Carlos H. F. M. Rodrigues
Carlos H. F. M. Rodrigues

Muito bom!

Mauricio Junior
Mauricio Junior

Fernando,
Você consegue fazer o mesmo exemplo com 10 threads ao mesmo tempo? Como ficaria isso no seu código acima?

Qual a sua opinião?

Comentários considerados ofensivos serão moderados.
BlackBerry

Parceiros

IBM
Abril
Hostmídia
PagSeguro
Impacta
Internet Innovation
Grupo Buscapé
Dialhost
O Ligador
RedeHost
Campus Party
Apiki
Tecla
Verisign
KingHost
DotStore
Café Azul - Social, Mobile e Smart TV
WebMatrixWebMatrix