Mostrando postagens com marcador Delegates. Mostrar todas as postagens
Mostrando postagens com marcador Delegates. Mostrar todas as postagens

quarta-feira, 1 de outubro de 2008

Dica: Application Idle

Quando se fala de processamento background em .net, você pode encontrar toneladas de formas diferentes de executar operações. A grande maioria delas envolvem threads diferentes da thread principal do programa (Application Pool, ThreadStart etc...).

Mas uma maneira interessante realizar atividades que não demandam de tanta carga de processamento pode ser o uso do evento Application.Idle.

Esse evento existe porque o .net tem como saber quando a thread principal está entrando no modo Idle (ocioso), e a execução do evento permite que se faça "alguma coisinha a mais" antes de entrar no modo idle.

Tenho utilizado o idle para implementar a persistência de um buffer de log de atividades de um sistema, e o desempenho é bem satisfatório, afinal, você deixar essa operação no evento Idle significa que ela não vai ficar sendo executada toda hora, e sim quando a aplicação teoricamente "não tiver nada de mais importante pra fazer", o que já é legal:

int contador = 0;

private void Form1_Load(object sender, System.EventArgs e)
{
Application.Idle += ( o, e) => { contador++ ; };
}


Esse é só um exemplo, mas aviso que nesse caso, o "Form1" em questão é o principal e
quando ele fecha, é porque a aplicação fecha, então tudo bem ter um lambda expression
aí (anônimo). Mas possivelmente não será uma boa prática para outros casos.

A razão disso está no fato de que como o evento Idle é estático, é muito importante que
no momento em que você vincula um delegate do tipo EventHandler a ele, é necesário
que você mantenha uma rotina de desvinculação preparada para retirar o evento, senão
isso pode se tornar um memory leak.
int contador = 0;
EventHandler myHandler = new EventHandler(Contar);

private void Contar( object sender, EventArgs e)
{
contador++;
}

private void Form1_Load(object sender, System.EventArgs e)
{
Application.Idle += myHandler
;
}

//o código de desvinculação pode ficar associado ao destrutor
~Form1()
{
Application.Idle -= myHandler ;
}


domingo, 21 de setembro de 2008

A evolução dos delegates

Ao longo das versões do C#, uma das funcionalidades que mais me reteve atenção como desenvolvedor foram Lambda Expressions. Desta forma, resolvi fazer um artigo expondo uma abordagem evolutiva sobre o tema (nada muito didático, meramente informativo):

C# 1.0

Quando tínhamos que escrever “ponteiros para uma função/método” no C# (óbvio que muitos não conhecem por esse nome, que é muito popular em C++, vou explicar melhor mais a frente), nós podíamos (e ainda podemos) adicioná-las em estruturas denominadas delegates da seguinte forma:



1- Se escreve o delegate, que é uma estrutura que funciona como um tipo, o qual aquele método vai ser vinculado, ou seja, se define uma referência com assinatura de método específica.

2- Se cria o método o qual se quer que o ponteiro aponte.

3- Com isso você pode adicionar (e remover) nessa referência qualquer método que tenha essa mesma assinatura, como se fosse uma lista de execução.

A conclusão que podemos chegar com delegates é que são mecanismos que permitem o agrupamento de vários métodos de diferentes classes para um pipeline execução. E justamente por isso, ele é utilizado em várias partes do .net framework, como threading, eventos, serialização etc.

Eventos
Como falei, no topo da estrutura de delegates está construída uma arquitetura de invocação implícita que ficou muito popular: eventos de componentes. Eventos são delegates especiais. Ele tem uma assinatura restrita que não deve retornar nada a não ser void, e só podem ser executados pela classe que os possui (classes filhas não executam diretamente eventos da classe pai). Essa especificidade é atribuída ao declarar a referência delegate a palavra chave event.



C# 2.0

As coisas ficaram um pouco mais práticas com o advento dos Anonymous Methods...

1 – Em muitos casos se deseja simplesmente executar uma operação vinculada a um evento de um componente (ex: setar visible=false no click do botão).
Isso significa que escrever um método unicamente pra fazer essa operação ser “burocracia demais”.

Pensando nisso, na versão do C# 2.0 foi criada, entre outras funcionalidades, Anonymous Methods, que é uma forma simplificada de escrever um método no contexto de um delegate:




Realmente simplificou mais, mas ainda não terminou...


C# 3.0

Tudo estava indo bem, até que apareceram essas tais lambda expressions, mas afinal, o que são lambda expressions? A resposta que mais gostei e a que uso é que é uma forma simplificada de escrever um delegate:

if ( querSaberMais?) {

goto: especificação do C# 3.0

if ( naoEntendiMuitoBem) {
Console.WriteLine(" Vou explicar com o nosso exemplo :-) ");
}
}

Na versão 2.0, criar um método anônimo para isso era a possibilidade mais ágil. Mas agora é possível proceder para resolver o mesmo problema com lambda expressions. A diferença é meramente uma questão de sintaxe:

Assim, assinar eventos simples como click’s de botão ficaram tão mais fáceis, que começei a inscrever muitos "onclicks" manualmente. Detalhe: a inferência de tipo é que faz o compilador procurar saber o tipo de "obj" e "e", o que é muito legal para quem tem dificuldades (como eu) de ficar decorando todos os XXXXEventArgs que tem poraí para cada evento diferente em função da vasta quantidade de XXXEventHandlers diferentes que os controles usam. :-)

Bom, é isso pessoal, no próximo post falarei sobre interfaces e Extension Methods, aguarde!