Skip to content

Projeto para estudo e demonstração destinado a iniciantes que desejam aprender sobre delegates e sua aplicação prática em C#

Notifications You must be signed in to change notification settings

Mmarcelinho/delegates_csharp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Delegates nos bastidores

Delegates é bastante comum no cenário .NET. Sendo conhecido como objeto que referência métodos, possuem diversos benefícios como:

  1. Encapsulação de métodos
  2. Callback
  3. Eventos
  4. Programação assíncrona
  5. Composição de métodos
  6. Delegação de responsabilidade

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.

Código:

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);

alt text

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.

alt text

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.

alt text

Delegates Assíncronos

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:

  1. O primeiro parâmetro é um parâmetro de entrada para o método.
  2. O segundo parâmetro é um delegado do tipo AsyncCallBack, que é um mecanismo de retorno de chamada que será invocado quando o método de destino for concluído.
  3. O terceiro parâmetro é usado para fornecer informações de estado assíncrono.

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.
  • O método BeginInvoke inicia o processamento assíncrono do método MeuMetodo.
  • O método 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.

Referências

Autores

Estes projetos de exemplo foram criados para fins educacionais. Marcelo é responsável pela criação e manutenção destes projetos.

Licença

Este projetos não possuem uma licença específica e são fornecidos apenas para fins de aprendizado e demonstração.

About

Projeto para estudo e demonstração destinado a iniciantes que desejam aprender sobre delegates e sua aplicação prática em C#

Topics

Resources

Stars

Watchers

Forks

Languages