No post anterior comentei sobre delegates, funcs e actions, mas infelizmente nao dei exemplos praticos de utilizacao.Nesta primeira parte do post, introduzirei o conceito de co-rotina e um exemplo de utilizacao.Co-RotinasCo-rotinas facilitam a programacao e visualizacao de codigo quando temos a necessidade de fazer chamadas assincronas de forma sequencial, ou seja, esperar o resultado de uma operacao antes de iniciar a proxima operacao, permitindo que tomemos decisoes de acordo com os resultados obtidos.Na programacao sincrona, o fluxo da execucao de um programa ocorre em uma mesma Thread. Na programacao assincrona, uma outra Thread e criada para execucao de uma determinada tarefa que tem um tempo de duracao indefinido, como por exemplo, chamadas a servicos da Web.Geralmente os metodos assincronos possuem eventos ou callbacks que sao disparados no momento em que a operacao for finalizada/completada, permitindo que o programador escreva codigo para tratar o resultado. A dor de cabeca vem quando a logica de uma aplicacao fica complexa, por exemplo, quando ha a necessidade de fazer varias chamadas utilizando eventos e callbacks, tornando o codigo dificil de ler, e sujeito a bugs.Para exemplificar, vamos escrever um programa simples que faz o download do codigo html de uma pagina, e imprime o conteudo numa aplicacao console: class Program { public static void Main(string[] args) { var webClient1 = new WebClient(); webClient1.DownloadStringCompleted += (s1, e1) => { Console.WriteLine(e1.Result); }; webClient1.DownloadStringAsync(new Uri("http://silverlightrush.blogspot.com")); Console.ReadLine(); } }Ok, esse codigo quando rodado ira instanciar uma classe chamada WebClient. Esta classe contem um metodo chamado DownloadStringAsync. Quando executado, o codigo nao "espera" o download terminar, pois e um metodo assincrono, e entao segue para a proxima linha. Antes de chamar o metodo, devemos subscrever ao evento DownloadStringCompleted. Atraves de uma expressao lambda, imprimimos o conteudo da pagina toda na tela.Agora vamos inserir uma regra de negocio ao programa. Digamos que ao terminar de ler o html, caso o Lenght do resultado seja maior que 1000 bytes, faremos uma outra chamada para baixar o html de um outro site. Entao o novo codigo ficou definido assim: var webClient1 = new WebClient(); webClient1.DownloadStringCompleted += (s1, e1) => { if (e1.Result.Length < 1000) Console.WriteLine(e1.Result); else { var webClient2 = new WebClient(); webClient2.DownloadStringCompleted += (s2, e2) => { Console.WriteLine(e2.Result); }; webClient2.DownloadStringAsync(new Uri("http://google.com")); }; }; webClient1.DownloadStringAsync(new Uri("http://silverlightrush.blogspot.com")); Console.ReadLine();Pronto. A nossa primeira regra de negocio foi inserida. O codigo funciona perfeitamente. Mas e se agora quisermos inserir uma nova regra baseado no resultado da segunda chamada ? Repare que o codigo esta dificil de ler e provavelmente vai ficar dificil de dar manutencao.Utilizando Co-RotinasUtilizando a tecnica de co-rotinas, escrevemos codigo sequencial, enfileirando diversas chamadas assincronas, utilizamos os tradicionais callbacks apenas dar prosseguimento ao fluxo de trabalho.Vamos ver como fica a sintaxe para esse mesmo programa mas com a utilizacao de co-rotinas: class Program { static string htmlBlogspot; static string htmlGoogle; public static void Main(string[] args) { Coroutine.BeginExecute(Operacoes()); Console.ReadLine(); } static IEnumerable<Routine> Operacoes() { yield return PrimeiraOperacao; if (htmlBlogspot.Length < 1000) { Console.WriteLine(htmlBlogspot); yield break; //cancela a execucao da proxima } yield return SegundaOperacao; Console.WriteLine(htmlGoogle); } static void PrimeiraOperacao(Action completed) { var webClient1 = new WebClient(); webClient1.DownloadStringCompleted