Eventos e Delegates
Autor: Jomar Sales | Publicado: 2012-03-10T17:44:00-08:00


EVENTOS E DELEGATES


Olá.

Pensado eu ser este um assunto muito discutido nos fóruns de desenvolvimento de software, resolvi demonstrar um exemplo simples e prático aqui no blog.

Observação: quem não conhece o termo DDD - Domain Driven Design, aconselho o livro (http://books.google.com.br/books?id=7dlaMs0SECsC&amp;printsec=frontcover&amp;redir_esc=y#v=onepage&amp;q&amp;f=false) do Eric Evans.

Imagine a seguinte situação: sua aplicação possui uma camada de apresentação (Windows Forms ou Asp.Net) que utiliza classes que estão localizadas em uma Class Library que faz parte da camada de Domínio (onde residem as entidades, repositórios, fábricas, etc). Uma dessa classes possui propriedades que, dada a ocorrência de alguns comportamentos, são alteradas e sua aplicação precisa ser notificada de tais alterações para exibir os resultados ao usuário. Não seria uma prática ideal adicionar o namespace System.Windows.Forms na referida classe para utilizar a classe MessageBox, já que não deve-se utilizar de tecnologias na camada de Domínio. Injetar referências para métodos que exibe telas da apresentação através de delegates também não é lá das melhores práticas.


Então, qual seria a solução mais viável? Eventos e Delegates!

O próprio padrão de arquitetura da Dot Net utiliza esses meios. Quando adicionamos um botão em nossa tela ou página, por exemplo, o objeto nos oferece vários eventos para utilizarmos ou não (Click, MouseUp, etc...). Podemos criar nosso próprios eventos para que possamos notificar a aplicação sobre qualquer alteração nas propriedades e comportamento do nosso objeto.
A tradução do conceito de eventos contido no site do msdn é a seguinte:
"Eventos&nbsp;habilitam uma classe&nbsp;ou objeto para notificar outras classes ou objetos quando ocorrer algo de interesse.&nbsp;A classe que envia (ou&nbsp;gera) o evento é chamado de&nbsp;publisher&nbsp;e as classes que recebem (ou&nbsp;lidam com) o evento são chamados&nbsp;assinantes."
Já o delegate é a referência (um ponteiro) para um método específico (assim como existem referências para variáveis) desde que tal método tenha a mesma assinatura do delegate.

Esses conceitos ficam melhor explicados na prática, lembrando que o exemplo é apenas para fins didáticos:

- Abra o Visual Studio 2010 e crie uma aplicação WindowsForms (Menu File &gt; New &gt; Project - Aba Windows &gt; WindowsFormsApplication) e dê o nome de ExemploEventos;

- No formulário padrão que o Visual Studio cria, insira dois buttons e um listbox;

- No Button1, altere a propriedade Text para Ligar;

- No Button2, altere a propriedade Text para Desligar;

- Deixe a aparência do seu formulário como na figura abaixo:





- Na SolutionExplorer, clique com o botão direito do mouse, na opção Add &gt; Class. Dê o nome de Carro.
- Nossa classe carro irá conter as seguintes propriedades dinâmicas:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Indica&nbsp;o&nbsp;total&nbsp;de&nbsp;litros&nbsp;existentes&nbsp;no&nbsp;tanque&nbsp;do&nbsp;carro&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;LitrosNoTanque&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Indica&nbsp;se&nbsp;o&nbsp;carro&nbsp;está&nbsp;ligado&nbsp;ou&nbsp;desligado&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;StatusLigado&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Indica&nbsp;se&nbsp;o&nbsp;carro&nbsp;está&nbsp;em&nbsp;movimento&nbsp;ou&nbsp;parado&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool&nbsp;StatusMovimento&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}


- A&nbsp;ideia&nbsp;é ter os seguintes comportamentos: ligar, desligar, partir e parar; e para cada alteração de comportamento do carro criar um evento notificador;

-Todo evento tem um TIPO, que geralmente é um delegate para um método. Então, temos que pensar na forma como&nbsp;iremos notificar nosso usuário. Neste exemplo pensei apenas em um método simples de notificação para exibir as mensagens específicas de cada status informado e um outro para recuperar a quantidade atual de litros no tanque. Por conversão, deve-se colocar a palavra EventHandle no final do nome de cada delegate que será um tipo para um evento. Então, os delegates da classe serão estes:

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;//&nbsp;Delegate&nbsp;para&nbsp;um&nbsp;método&nbsp;simples&nbsp;de&nbsp;exibição&nbsp;de&nbsp;status
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;delegate&nbsp;void&nbsp;InformacoesCarroEventHandle();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Delegate&nbsp;para&nbsp;um&nbsp;método&nbsp;que&nbsp;utiliza&nbsp;a&nbsp;propriedade&nbsp;LitrosNoTanque,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;através&nbsp;da&nbsp;variável&nbsp;inteira&nbsp;passada&nbsp;como&nbsp;parâmetro&nbsp;no&nbsp;método&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;para&nbsp;informar&nbsp;tal&nbsp;status&nbsp;ao&nbsp;usuário
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;delegate&nbsp;void&nbsp;InformacaoTanqueEventHandle(int&nbsp;litrosNoTanque);

- Pronto, nossos delegates foram declarados.

-Teremos um evento para cada notificação desejada. A sintaxe de declaração é a seguinte:
&nbsp; &nbsp;&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Evento&nbsp;para&nbsp;notificar&nbsp;que&nbsp;o&nbsp;carro&nbsp;ligou
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;event&nbsp;InformacoesCarroEventHandle&nbsp;CarroLigado;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Evento&nbsp;para&nbsp;notificar&nbsp;que&nbsp;o&nbsp;carro&nbsp;desligou&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;event&nbsp;InformacoesCarroEventHandle&nbsp;CarroDesligado;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Evento&nbsp;para&nbsp;notificar&nbsp;que&nbsp;o&nbsp;carro&nbsp;está&nbsp;em&nbsp;movimento&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;event&nbsp;InformacoesCarroEventHandle&nbsp;CarroEmMovimento;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Evento&nbsp;para&nbsp;notificar&nbsp;que&nbsp;o&nbsp;carro&nbsp;parou&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;event&nbsp;InformacoesCarroEventHandle&nbsp;CarroParado;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Evento&nbsp;para&nbsp;notificar&nbsp;que&nbsp;o&nbsp;carro&nbsp;está&nbsp;sem&nbsp;gasolina&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;event&nbsp;InformacoesCarroEventHandle&nbsp;TanqueVazio;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Evento&nbsp;para&nbsp;notificar&nbsp;a&nbsp;quantidade&nbsp;de&nbsp;litros&nbsp;no&nbsp;tanque&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;event&nbsp;InformacaoTanqueEventHandle&nbsp;QuantidadeLitrosNoTanque;


- Nossa classe Carro terá um construtor que informará a quantidade de gasolina inserida no tanque do carro:

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;//&nbsp;Contrutor&nbsp;do&nbsp;objeto.&nbsp;Inicializa&nbsp;a&nbsp;propriedade&nbsp;LitrosNoTanque
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Carro(int&nbsp;litrosNoTanque)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.LitrosNoTanque&nbsp;=&nbsp;litrosNoTanque;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}


- O primeiro método é de ligar. Observe que, se o carro estiver ligado ou sem gasolina tal status é notificado pelo seu evento específico e, assim que o carro é ligado, o evento de notificação é chamado:


&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Efetua&nbsp;verificações&nbsp;e&nbsp;liga&nbsp;o&nbsp;carro&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;Ligar()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(this.StatusLigado)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CarroLigado();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(this.LitrosNoTanque.Equals(0))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.TanqueVazio();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.StatusLigado&nbsp;=&nbsp;true;
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CarroLigado();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}



- Da mesma forma acontece com o método desligar:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Efetua&nbsp;validações&nbsp;e&nbsp;desliga&nbsp;o&nbsp;carro&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;Desligar()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!this.StatusLigado)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CarroDesligado();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.StatusLigado&nbsp;=&nbsp;false;
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CarroDesligado();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}


- O processo de movimentar o carro possui mais detalhes. Após dar a partida no carro inicia o processo de consumo de combustível que também é notificado com seu evento:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Efetua&nbsp;validações&nbsp;e&nbsp;dar&nbsp;a&nbsp;partida&nbsp;no&nbsp;carro.&nbsp;Da&nbsp;a&nbsp;partira&nbsp;no&nbsp;carro&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;e&nbsp;inicia&nbsp;o&nbsp;processo&nbsp;de&nbsp;consumo&nbsp;de&nbsp;gasolina
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;Partir()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!this.StatusLigado)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CarroDesligado();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(this.LitrosNoTanque.Equals(0))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.TanqueVazio();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.StatusMovimento&nbsp;=&nbsp;true;
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CarroEmMovimento();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(this.LitrosNoTanque&nbsp;&gt;&nbsp;0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.Threading.Thread.Sleep(1000);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.LitrosNoTanque--;
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.QuantidadeLitrosNoTanque(LitrosNoTanque);
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(LitrosNoTanque.Equals(0)&nbsp;||&nbsp;!this.StatusLigado)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.TanqueVazio();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.Parar();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.Desligar();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}


- E por fim, o método de parar:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Efetua&nbsp;validações&nbsp;e&nbsp;pára&nbsp;o&nbsp;carro&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;Parar()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!this.StatusLigado)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CarroDesligado();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!this.StatusMovimento)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CarroParado();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.StatusMovimento&nbsp;=&nbsp;false;
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.CarroParado();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}


-Nossa classe Carro está pronta. Precisamos agora utilizá-la em nossa windows application. Volte para a janela e pressione F7 para exibir seu CodeBehind.

- No topo da classe declare uma propriedade dinâmica da classe Carro.&nbsp;Logo abaixo, no construtor da janela, instancie o nosso carro e crie os event handles de notificações:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Carro&nbsp;Palio&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Form1()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.Palio&nbsp;=&nbsp;new&nbsp;Carro(20);&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Palio.CarroLigado&nbsp;+=&nbsp;new&nbsp;Carro.InformacoesCarroEventHandle(Palio_CarroLigadoEventHandle);
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Palio.CarroDesligado&nbsp;+=&nbsp;new&nbsp;Carro.InformacoesCarroEventHandle(Palio_CarroDesligadoEventHandle);
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Palio.CarroEmMovimento&nbsp;+=&nbsp;new&nbsp;Carro.InformacoesCarroEventHandle(Palio_CarroEmMovimentoEventHandle);
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Palio.CarroParado&nbsp;+=&nbsp;new&nbsp;Carro.InformacoesCarroEventHandle(Palio_CarroParadoEventHandle);
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Palio.TanqueVazio&nbsp;+=&nbsp;new&nbsp;Carro.InformacoesCarroEventHandle(Palio_TanqueVazioEventHandle);
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Palio.QuantidadeLitrosNoTanque&nbsp;+=&nbsp;new&nbsp;Carro.InformacaoTanqueEventHandle(Palio_LitrosNoTanqueEventHandle);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;Palio_LitrosNoTanqueEventHandle(int&nbsp;litrosNoTanque)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Items.Add(string.Format("Capacidade&nbsp;atual&nbsp;do&nbsp;Tanque&nbsp;{0}",&nbsp;litrosNoTanque));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;Palio_CarroParadoEventHandle()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Items.Add("O&nbsp;carro&nbsp;parou!");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;Palio_TanqueVazioEventHandle()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Items.Add("O&nbsp;carro&nbsp;está&nbsp;sem&nbsp;gasolina!");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;Palio_CarroEmMovimentoEventHandle()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Items.Add("O&nbsp;carro&nbsp;está&nbsp;andando!");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;Palio_CarroDesligadoEventHandle()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Items.Add("O&nbsp;carro&nbsp;desligou!");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;Palio_CarroLigadoEventHandle()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listBox1.Items.Add("O&nbsp;Carro&nbsp;ligou!");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}


- Volte para a janela e dê um duplo clique no button1 (isso criará um event handle para o evento click :-) e insira o trecho de código abaixo:

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;private&nbsp;void&nbsp;button1_Click(object&nbsp;sender,&nbsp;EventArgs&nbsp;e)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.Palio.Ligar();
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;t&nbsp;=&nbsp;new&nbsp;Thread(new&nbsp;ThreadStart(Palio.Partir));
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CheckForIllegalCrossThreadCalls&nbsp;=&nbsp;false;
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.Start();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}



- Explicando o código do button1:
&nbsp; * A primeira linha chama o método ligar do objeto pálio.
&nbsp; * O método partir, que é chamado logo em seguida é um método que ocorre em "paralelo" com o método ligar para que a janela consiga exibir as mensagens a cada processamento do consumo de combustível. então, foi criada uma Thread além da Thread principal para processar o método de forma assíncrona.
&nbsp; * A terceira linha desabilita a checagem de chamadas cruzadas por threads.
&nbsp; * A quarta inicia a Thread efetivando o procedimento partir.

- Volte para a janela e dê um duplo clique no button2 e insira o código para parar o carro. Como o método partir está sendo executado em segundo plano, este método pode ser chamado enquanto o carro estiver consumindo combustível:

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;private&nbsp;void&nbsp;button2_Click(object&nbsp;sender,&nbsp;EventArgs&nbsp;e)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.Palio.Desligar();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}


- Salve e construa sua solução. Pressione F5 para iniciar a plicação, clique no botão Ligar e veja as notificações, como na janela abaixo:




Então é isso pessoal. Espero que ajude!!!

Referências:
http://msdn.microsoft.com/pt-br/library/awbftdfh(v=vs.90).aspx
http://www.macoratti.net/11/05/c_dlg1.htm 
http://msdn.microsoft.com/en-us/library/orm-9780596516109-03-09.aspx