O namespace System.Threading.Tasks trás alguns métodos que permitem realizar tarefas de forma assíncrona e de uma forma bastante simples de implementar. Dos novos métodos/tipos deste namespace, podem destacar-se 3:
- System.Threading.Tasks.Task que representa uma operação assíncrona que não retorna valores;
- System.Threading.Tasks.Task(Of TResult) que representa uma operação assíncrona que retorna valores;
- System.Threading.Tasks.TaskScheduler que fornece métodos estáticos que permitem executar uma Task de acordo com uma pré-definição (schedule);
Nota: Neste artigo serão focados apenas os dois primeiros.
Para o seguinte exemplo importar os seguinte namespaces:
Imports System.Threading
Imports System.Threading.Tasks
De uma forma geral uma Task funciona do seguinte modo:
' Define uma nova Task utilizando uma expressão Lambda
' que não será executada automáticamente após a declaração
Dim t1 As New Task(Sub()
For x As Integer = 0 To 50
Console.WriteLine("t1 - " & x.ToString())
Thread.Sleep(200)
Next
End Sub)
' Inicia a Task
t1.Start()
Console.WriteLine("Tasks1 iniciada!")
' Define uma Action Delegate que irá encapsular um método
Dim doSomething As New Action(Sub()
For x As Integer = 0 To 50
Console.WriteLine("t2 - " & x.ToString())
Thread.Sleep(200)
Next
End Sub)
' Define uma nova Task e inicia-a
Dim t2 As New Task(doSomething)
t2.Start()
Console.WriteLine("Tasks2 iniciada!")
' Aguarda que as tasks terminem antes de continuar
Tasks.Task.WaitAll(New Task() {t1, t2})
Console.WriteLine("Tasks terminadas!")
Este exemplo mostra como criar uma tarefa simples, usando uma Lambda Expression, e usando um Action Delegate. Mostra também como usar o método WaitAll() e com isso esperar que todas as tarefas terminem antes de avançar com o código.
Mas por uma questão de performance é aconselhado que se utilize o seguinte método para a criação de tarefas:
' Define uma nova Task, usando o método Factory.StartNew()
Dim t3 As Task = Task.Factory.StartNew(doSomething)
Console.WriteLine("Tasks3 iniciada!")
Este método cria uma tarefa e inicia-a imediatamente, não podendo no entanto ser usado em algumas situações (como por exemplo caso a tarefa necessite de ser executada posteriormente).
Mas todos estes exemplos não retornam valores! É muitas vezes necessário receber informação de uma determinada tarefa e nestes casos podemos utilizar o método Tasks.Task(Of TResult).
Eis um exemplo da sua utilização, que serve unicamente para mostrar como receber um resultado de uma tarefa, uma vez que não é um exemplo que necessite de ser executado desta forma.
'Utiliza uma task para recolher o nome de todos os paises
Dim countries = Task.Factory.StartNew(Of List(Of CultureInfo))(
Function()
Return CultureInfo.GetCultures(CultureTypes.AllCultures).ToList()
End Function)
' Espera que a task complete de modo a
' garantir que tem todos os resultados
countries.Wait()
' Mostra todos os paises de língua Inglesa
For Each item As CultureInfo In
countries.Result.Where(Function(c) c.Name.Contains("en") And
c.Name.Length > 2)
Console.WriteLine(item.NativeName)
Next
Console.ReadKey()
Este exemplo, onde é necessário importar os namespaces System.Threading.Tasks e System.Globalization, recolhe a lista de todos os países, espera que a tarefa termine, e depois, usando Lambda Expressions, filtra todos os países de língua inglesa. O resultado, ou seja, o valor produzido e que será devolvido, é obtido através da propriedade Result.
Como a opções Option Infer está definida como On, não é necessário declarar a variável “countries” explicitando o tipo, uma vez que é inferido o tipo correcto(simplificando desta forma o código). Neste caso seria:
Dim countries As Task(Of List(Of CultureInfo)) = ...
Como podem ver nos exemplos mostrados, a criação de tarefas em paralelo é bastante simples e está bastante optimizada no Visual Studio 2010/.NET Framework 4.0.
0 comentários:
Enviar um comentário