Loading repository data…
Loading repository data…
Mmarcelinho / repository
Projeto para estudo e demonstração destinado a iniciantes que desejam aprender sobre delegates e sua aplicação prática em C#
Delegates é bastante comum no cenário .NET. Sendo conhecido como objeto que referência métodos, possuem diversos benefícios como:
que permite uma programação mais flexível.
Partindo desse ponto, será abordado abaixo como o "Objeto que referência métodos" realmente funciona por "debaixo dos panos" e como o compilador e o CLR trabalham para implementar o delegates.
public delegate void MeuDelegate(int valor);
Ao escrever o código acima, o compilador define uma classe completa a esse exemplo:
class MyDelegate : System.MulticastDelegate
{
public MeuDelegate(Object object, Inptr method);
public virtual void Invoke(Int32 valor);
public virtual IAsyncResult BeginInvoke(Int32 valor,
AsyncCallback callback, object object);
public virtual void EndInvoke(IAsyncResult result);
}
E esta classe tem quatro partes principais:
Construtor: Utilizado para criar uma instância do delegado, aceitando dois parâmetros: Um objeto e um ponteiro para um método.
Método Invoke Método utilizado para chamar o método associado ao delegado no mesmo thread.
Metódo BeginInvoke Método utilizado para chamar o método de forma assíncrona.
Método EndInvoke Método utilizado para finalizar uma chamada assíncrona feita com BeginInvoke.
Existem também três campos internos que desvendam como os métodos ( estáticos e de instância ) são apontados, sendo provavelmente a característica mais significativa nos delegates.
_target Se o método associado ao delegado é estático, este campo é nulo. Se for um método de instância, ele contém uma referência ao objeto que contém o método.
methodptr Este é um número especial que identifica o método associado ao delegado.
invocationlist
Este campo geralmente é null e é usado para armazenar uma lista de delegados, geralmente quando você combina vários delegados em um único delegado.
Aqui um exemplo de como esses campos funcionam com método estático e método de instância.
MeuDelegate objetoEstatico = new MeuDelegate(Classe.MetodoStatic);
MeuDelegate objetoInstancia = new MeuDelegate(new Classe().MetodoInstancia);
Se você cria um delegado para um método estático, o campo _target é nulo e o _methodptr aponta para o método estático.
Se for um método de instância, _target aponta para o objeto que contém o método e _methodptr aponta para o método em si.
O método .Combine é usado para combinar vários delegados em um único delegado. Quando você combina delegados, o C# cria um novo objeto delegado para representar a combinação dos delegados originais.
MeuDelegate objetoEstatico = new MeuDelegate(Classe.MetodoStatic);
MeuDelegate objetoInstancia = new MeuDelegate(new Classe().MetodoInstancia);
MeuDelegate objetoListaDeDelegates = null;
objetoListaDeDelegates = (MeuDelegate) Delegate.Combine( objetoListaDeDelegates, objetoEstatico);
objetoListaDeDelegates = (MDelegate) Delegate.Combine( objetoListaDeDelegates, objetoInstancia);
No exemplo dado:
objetoEstatico é um delegado que representa um método estático.objetoInstancia é um delegado que representa um método de instância.objetoListaDeDelegates é inicialmente nulo, mas depois de combinar os delegados, ele representa um novo delegado que combina os métodos de objetoEstatico e objetoInstancia.Os delegates em C# podem chamar métodos de forma assíncrona, o que significa que eles podem iniciar a execução de um método em um thread separado e retornar imediatamente ao thread principal.
Quando você usa o método BeginInvoke em um delegate, o CLR coloca a solicitação na fila e retorna ao thread principal. O método de destino será então chamado em um thread do pool de threads, permitindo que o thread principal execute outras tarefas enquanto aguarda a conclusão do método de destino.
O método BeginInvoke tem três parâmetros:
AsyncCallBack, que é um mecanismo de retorno de chamada que será invocado quando o método de destino for concluído.Se você não especificar um retorno de chamada, o método EndInvoke será usado no thread original para obter o valor de retorno do processamento assíncrono. Se um retorno de chamada estiver presente, o método EndInvoke será chamado no método de retorno de chamada.
Exemplo de código de um delegate assíncrono:
using System;
using System.Threading;
public delegate int MeuDelegado(int valor);
class Program
{
static void Main(string[] args)
{
MinhaClasse minhaClasse = new MinhaClasse();
MeuDelegado meuDelegado = new MeuDelegado(minhaClasse.MeuMetodo);
// Inicia o processamento assíncrono
IAsyncResult resultadoAssincrono = meuDelegado.BeginInvoke(5, new AsyncCallback(MeuCallback), "Informação do estado");
Console.WriteLine("Do thread principal");
Console.ReadLine();
}
public static void MeuCallback(IAsyncResult resultadoAssincrono)
{
AsyncResult resultado = (AsyncResult)resultadoAssincrono;
MeuDelegado meuDelegado = (MeuDelegado)resultado.AsyncDelegate;
int resultadoMetodo = meuDelegado.EndInvoke(resultadoAssincrono);
Console.WriteLine("Resultado do callback: " + resultadoMetodo);
// Informação do estado do thread principal
string mensagem = (string)resultadoAssincrono.AsyncState;
Console.WriteLine(mensagem);
}
}
class MinhaClasse
{
public int MeuMetodo(int valor)
{
Thread.Sleep(10000);
return (valor * valor);
}
}
Neste exemplo:
MeuDelegado é um delegado que representa um método que retorna um inteiro e aceita um inteiro como parâmetro.MinhaClasse contém o método MeuMetodo, que será chamado de forma assíncrona.BeginInvoke inicia o processamento assíncrono do método MeuMetodo.MeuCallback é chamado quando o método MeuMetodo é concluído, exibindo o resultado do callback e a informação de estado do thread principal.Assumindo que o método MeuMetodo retorna o quadrado do valor passado como argumento, o resultado do callback será o quadrado de 5, ou seja, 25.
Portanto, a saída seria:
Do thread principal
Resultado do callback: 25
Informação do estado
Delegates é um objeto que se refere a métodos e pode ser usado tanto em processos assíncronos quanto síncronos, permitindo a execução de métodos em outras threads. O uso de processamento assíncrono é especialmente útil para realizar tarefas em segundo plano, sem bloquear o thread principal.
Estes projetos de exemplo foram criados para fins educacionais. Marcelo é responsável pela criação e manutenção destes projetos.
Este projetos não possuem uma licença específica e são fornecidos apenas para fins de aprendizado e demonstração.