Download - Programação assíncrona com c sharp
Programação assíncrona com C# 5André Bires @ Take.netJaneiro de 2014
Il Pizzeria Ritardato
Pizzeria Ritardato 5 garçons 10 mesas
Pizzeria Ritardato Garçom espera na cozinha o pedido
Pizzeria Ritardato + de 5 pedidos = Clientes esperando
Pizzeria Ritardato Contratação de + 5 garçons Total = 10
Pizzeria Ritardato Custo > Receita = Prejuízos
Il Pizzeria Veloce
Pizzeria Veloce 3 garçons 10 mesas
Pizzeria Veloce Garçom leva pedido na cozinha e volta para o balcão
Pizzeria Veloce Campainha Garçom pedido != garçom entrega
Pizzeria Veloce Aumento da freguesia 3 garçons + que suficientes Ampliação para 15 mesas
Pizzeria Veloce Mesmo custo com Maior receita = Maior eficiência
?
!
Programação assíncrona Uso eficiente dos recursos computacionais
NUNCA bloquear uma thread
Thread bloqueada = Dinheiro jogado fora
Thread bloqueada = Destruição da natureza
Programação assíncrona Retorno ao threadpool Notificação de conclusão
Não é o mesmo que programação paralela!
Programação assíncrona Pizzaria: Servidor Mesa/cliente: Aplicação Garçom: Thread Salário do garçom: Memória da
thread Balcão: Thread pool
Programação assíncrona Pedido: Requisição externa Pizzaiolo: Serviço externo Pizza: Resultado da requisição Campainha: Notificação
Programação assíncrona com C# 5
Programação assíncrona com C# Asynchronous Programming Model
(APM)
Programação assíncrona com C# Asynchronous Programming Model
(APM) Event-based Asynchronous Pattern
(EAP)
Programação assíncrona com C# Asynchronous Programming Model
(APM) Event-based Asynchronous Pattern
(EAP) Task-based Asynchronous Pattern (TAP)
Programação assíncrona com C# Asynchronous Programming Model
(APM) Event-based Asynchronous Pattern
(EAP) Task-based Asynchronous Pattern (TAP)
Task-based Asynchronous Pattern Task ou Task<T> C# 4 Task = Promisse ou Future
Task-based Asynchronous Pattern () => { } Threadpool
Task-based Asynchronous Pattern private void Example1Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API...";
Task<string> task = Task.Run(() => GetName(1));
nameTextBox.Text = task.Result; toolStripStatusLabel.Text = "Done"; }
Task-based Asynchronous Pattern private void Example1Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API...";
Task<string> task = Task.Run(() => GetName(1));
nameTextBox.Text = task.Result; toolStripStatusLabel.Text = "Done"; }
Task-based Asynchronous Pattern ContinueWith
Task-based Asynchronous Pattern private void Example2Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API...";
Task.Run(() => GetName(1)) .ContinueWith(t => this.Invoke(new Action(() => { nameTextBox.Text = t.Result; toolStripStatusLabel.Text = "Done"; })) );}
Task-based Asynchronous Pattern private void Example2Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API...";
Task.Run(() => GetName(1)) .ContinueWith(t => this.Invoke(new Action(() => { nameTextBox.Text = t.Result; toolStripStatusLabel.Text = "Done"; })) );}
Task-based Asynchronous Pattern private void Example2Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API...";
Task.Run(() => GetName(1)) .ContinueWith(t => this.Invoke(new Action(() => { nameTextBox.Text = t.Result; toolStripStatusLabel.Text = "Done"; })) );}
Task-based Asynchronous Pattern private void Example2Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API...";
Task.Run(() => GetName(1)) .ContinueWith(t => this.Invoke(new Action(() => { nameTextBox.Text = t.Result; toolStripStatusLabel.Text = "Done"; })) );}
Task-based Asynchronous Patternprivate void Example1Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API...";
for (int i = 0; i < repeatNumericUpDown.Value; i++) { Task<string> task = Task.Run(() => GetName(1)); nameTextBox.AppendText(task.Result); nameTextBox.AppendText(Environment.NewLine); }
toolStripStatusLabel.Text = "Done"; }
private void Example2Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API..."; GetNames(Convert.ToInt32(repeatNumericUpDown.Value));} private void GetNames(int remaining) { Task.Run(() => GetName(1)) .ContinueWith(t => this.Invoke(new Action(() => { nameTextBox.AppendText(t.Result); nameTextBox.AppendText(Environment.NewLine); remaining--; if (remaining > 0) { GetNames(remaining); } else { toolStripStatusLabel.Text = "Done"; } }) ) ); }
Task-based Asynchronous Pattern C# 5.0 (.NET 4.5)
async
await
Task-based Asynchronous Pattern Método I/O que retorne uma Task Event handler assíncrono
Task-based Asynchronous Pattern private async void Example3Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API..."; nameTextBox.Text = await GetNameAsync(1); toolStripStatusLabel.Text = "Done"; }
Task-based Asynchronous Patternprivate async void Example3Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API...";
for (int i = 0; i < repeatNumericUpDown.Value; i++) { nameTextBox.AppendText(await GetNameAsync(1)); nameTextBox.AppendText(Environment.NewLine); } toolStripStatusLabel.Text = "Done"; }
Task-based Asynchronous Pattern private async void Example3Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API..."; nameTextBox.Text = await GetNameAsync(1); toolStripStatusLabel.Text = "Done"; }
Task-based Asynchronous Pattern private async void Example3Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API..."; nameTextBox.Text = await GetNameAsync(1); toolStripStatusLabel.Text = "Done"; }
Task-based Asynchronous Pattern private async void Example3Button_Click(object sender, EventArgs e) { toolStripStatusLabel.Text = "Calling the API..."; nameTextBox.Text = await GetNameAsync(1); toolStripStatusLabel.Text = "Done"; }
Primeiro estado
Segundo estado
Task-based Asynchronous Pattern
Overhead!
Task-based Asynchronous Pattern API verdadeiramente assíncronas = Completion port (Windows)
Task-based Asynchronous Pattern TcpClient HttpClient Socket Etc.
Task-based Asynchronous Pattern Async wrappers = EVIL
private Task<string> GetNameAsyncWrapper(int id){ return Task.Run(() => { return GetName(id); });}
private string GetName(int id) { // Synchronous implemementation }
Task-based Asynchronous Pattern
private Task<string> GetNameAsyncWrapper(int id){ return Task.Run(() => { return GetName(id); });}
private string GetName(int id) { // Synchronous implemementation }
Task-based Asynchronous Pattern
private async Task<string> GetNameAsync(int id) { string url = string.Format("http://localhost:3803/names/{0}", id); using (var client = new HttpClient()) { var httpResponseMessage = await client.GetAsync(url); if (httpResponseMessage.IsSuccessStatusCode) { return await httpResponseMessage.Content .ReadAsStringAsync(); } else { return httpResponseMessage.ReasonPhrase; } } }
Task-based Asynchronous Pattern
Task-based Asynchronous Pattern Código legado requer muitas alterações
async =
infecção
public string Get(int id, bool delay = false){ if (delay) { // Simula uma chamada externa, como banco de dados Thread.Sleep(3000); }
return string.Format( "{0} {1}", _firstNames[_random.Next(_firstNames.Length - 1)], _lastNames[_random.Next(_lastNames.Length - 1)]); }
Task-based Asynchronous Pattern
public async Task<string> GetAsync(int id, bool delay = false) { if (delay) { // Simula uma chamada externa, como banco de dados await Task.Delay(3000); }
return string.Format( "{0} {1}", _firstNames[_random.Next(_firstNames.Length - 1)], _lastNames[_random.Next(_lastNames.Length - 1)]); }
Task-based Asynchronous Pattern
Task-based Asynchronous PatternBoas práticas: async void apenas em event handlers ConfigureAwait(false) em bibliotecas
Task-based Asynchronous Pattern Callstack é diferente do código síncrono
?