C# - Concorrência , Paralelismo, Multithread e Assincronismo no .NET - II
Hoje vamos continuar a tratar dos conceitos de concorrência, paralelismo, multithreading e assincronismo aplicados na plataforma .NET focando a programação assíncrona. |
Continuando a primeira parte do artigo onde apresentamos os conceitos sobre concorrência, paralelismo, multithread e assincronismo vamos tratar com a programação assíncrona.
A programação assíncrona
Vamos iniciar analisando um trecho de código usando na programação assíncrona na linguagem C#.
using System;
using System.Threading.Tasks;
namespace C_Async1
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Chamando DemoAsync()...");
await DemoAsync();
Console.WriteLine("Após chamar DemoAsync...");
Console.ReadLine();
}
static async Task DemoAsync()
{
int val = 15;
// aguarda 1 segundo - assíncro
await Task.Delay(TimeSpan.FromSeconds(1));
val *= 2;
// aguarda 1 segundo - assíncrono
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(val);
}
}
}
|
Na linguagem C# a programação assíncrona usa as palavras chave async e await.
Um método assíncrono começa a ser executado de forma síncrona, como qualquer outro método.
Dentro de um método assíncrono, a palavra-chave await executa uma espera assíncrona em seu argumento :
Você pode pensar em um método assíncrono como tendo várias partes síncronas, divididas por instruções await.
A primeira parte síncrona é executada em qualquer que seja a thread que chama o método, mas onde as outras partes síncronas são executadas ?
A resposta é um
pouco complicada.
Quando você espera uma tarefa (o cenário mais comum), um contexto é
capturado quando o await decide pausar o método. Este contexto é o
SynchronizationContext atual, a menos que seja nulo, caso em que o contexto
é o TaskScheduler atual.
O método retoma a
execução dentro desse contexto capturado. Normalmente, esse contexto é o
contexto da IU (se você estiver no thread de IU), um contexto de
solicitação ASP.NET (se você estiver processando uma solicitação ASP.NET)
ou o contexto do pool de threads (a maioria das outras situações).
Portanto, no código anterior, todas as partes síncronas tentarão retomar no
contexto original. Se você chamar o método DemoAsync a
partir de um thread de IU, cada uma de suas partes síncronas será executada
nessa thread de IU; mas se você chamá-lo de um thread do pool de threads, cada
uma de suas partes síncronas será executada em um thread do pool de threads.
Você pode evitar esse comportamento padrão aguardando o resultado do método de
extensão ConfigureAwait e passando false para o parâmetro
continueOnCapturedContext.
O código a seguir do método DemoAsync2 começará na thread de chamada e, depois de ser pausado por um await, ele continuará em uma thread do pool de threads:
async Task DemoAsync2()
{
int val = 15;
// aguarda 1 segundo - assíncro
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
val *= 2;
// aguarda 1 segundo - assíncro
await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);
Console.WriteLine(val.ToString());
}
|
Dessa forma a palavra-chave await não se limita a trabalhar com um task; pode funcionar com qualquer tipo de espera que siga um certo padrão.
Como exemplo, a API do Windows Runtime define suas próprias interfaces para operações assíncronas. Eles não são conversíveis em Task, mas seguem o padrão esperado, portanto, você pode aguardá-los diretamente.
Esses
aguardáveis são mais comuns em aplicativos da Windows Store, mas na maioria das
vezes, aguardar exigirá uma usar um Task ou um Task<T>.
Existem duas maneiras básicas de criar uma instância de
Task. Algumas tarefas representam o código real que uma CPU deve
executar; essas tarefas computacionais devem ser criadas chamando
Task.Run (ou TaskFactory.StartNew
se você precisar que elas sejam executadas em um agendador específico).
Outras tarefas representam uma notificação; essas tarefas baseadas em eventos são criadas por TaskCompletionSource<T> (ou um de seus atalhos). No entanto, a maioria das tarefas de E/S usa TaskCompletionSource<T>.
E estamos conversados...
Aquele que crê
no Filho (Jesus) tem a vida eterna; mas aquele que não crê no Filho não verá a
vida, mas a ira de Deus sobre ele permanece.
João 3:36
Referências:
VB .NET - Programação assíncrona com Async e Wait
C# - Programação Assíncrona com async e ..
C# - Usando async/await - Macoratti.net
C# - Programação Assíncrona como : Asycn e Task
WPF - Usando async/await para melhorar o ..
ADO .NET - Acesso Assíncrono aos dados