Fala Galera,

Hoje vamos abordar dois conceitos muitos utilizados na plataforma .NET,  a programação em paralelo e em tarefas.

Task Parallel Library (TPL) é a biblioteca responsável por podermos usar os conceitos deTask e de Parallel no .NET

Essa biblioteca contém um conjunto de API’s (Application Programming Interfaces) para simplificar o processo de adicionar paralelismo e concorrência em uma aplicação.

O que é Task Parallel Library

Como foi dito, a TPL é uma biblioteca que contém um conjunto de APIs públicas e essasAPIs estão localizados no namespace System.Threading e System.Threading.Tasks.

E como funciona a TPL? Para se executar uma programação Paralela ou em Tarefas internamente a TPL funciona da seguinte maneira, quando criamos uma tarefa por exemplo a TPL dimensiona o grau de simultaneidade dinamicamente para usar todos os processadores disponíveis de forma mais eficiente. Além disso, com a TPL podemos executar particionamento de tarefas, suporte a cancelamento e o gerenciamento de estado.

Como funciona um aplicação multi thread

Quando nós criamos uma aplicação multi thread, o sistema operacional associa cada thread a um core do seu computador porém na realidade algumas threads podem ser executadas em core distintos e algumas vezes não.

Thread

Então para se resolver o problema acima foi criado um mecanismo chamado Task. Uma tarefa nada mais é que uma operação assíncrona que será gerenciado pela TPL utilizando os recursos do ThreadPool. Ao gerenciar as tarefas, a TPL consegue alocar todas as threads para ser executadas em todos os core disponíveis.

Thread2

Utilizando as tarefas obtemos os benefícios da programação multi thread de forma mais simples com garantia de isolamento e gerenciamento de concorrência.

Data Parallelism

Paralelismo de dados é um conceito aonde temos cenários em que a mesma operação é executada simultaneamente ou seja em paralelo em elementos de uma fonte dados.

No paralelismo de dados, a fonte de dados é particionada em diversas thread aonde cada thread podem operar simultaneamente em diferentes segmentos do código.

A TPL dá suporte a programação ao paralelismo utilizando a classe System.Threading.Tasks.Parallel. Essa classe fornece métodos estáticos para se criar loop em paralelo.

Por baixo dos panos quando um loop em paralelo é executado a TPL usa uma classe chamada Partioner<T> para que o loop funcione simultaneamente em várias partes, assim o TaskScheduler particiona as tarefas com base na carga de trabalho e nos recursos disponíveis do sistema operacional. Algumas vezes é necessário redistribuir a carga entre várias threads e processadores se a carga de trabalho ficar desbalanceada.

Veja o exemplo abaixo:

// For tradicional
for (int i = 0; i < 100000; i++)
  Console.WriteLine($"Exibindo o loop pelo indice {i}");

// Mesmo for executado em paralelo
System.Threading.Tasks.Parallel.For(0, 100000, (i) =>
{
   Console.WriteLine($"Exibindo o loop pelo indice {i}");
});

Task Parallelism

Uma tarefa nada mais é que um operação assíncrona. Uma tarefa é similar a uma thread porém com um nível maior de abstração. Podemos criar uma ou mais tarefas e essas tarefas serão executadas de formas independentes porém sua execução será simultânea.

O uso de tarefas fornecem dois principais benefícios:

  • Uso mais eficiente e mais dimensionável de recursos do sistema.
  • Maior controle programático sobre uma tarefa do que uma simples thread

Todas as tarefas são enfileiradas no ThreadPool, ele foi aprimorado com algoritmos que determinam e ajustam o números de threads para fornecer um balanceamento de carga a maximizar o uso dos recursos do sistema operacional.

Tarefas e estruturas criadas em torno delas fornecem um conjunto de APIs que oferecem suporte a cancelamento, continuações, tratamento de exceção robusto, status detalhado de uma tarefa, agendamento e entre outros.

Uma tarefa que não retorna valor, ela é representada pelo classe System.Threading.Tasks.Task. Uma tarefa que retorna valor é representada pela classe System.Threading.Tasks.Task<TResult>. Uma tarefa lida com todos os detalhes de infraestrutura e fornece métodos e propriedades  que são acessíveis durante a vida útil da tarefa.

Veja o exemplo abaixo:

static void Main(string[] args)
{
    var task = Task.Factory.StartNew(() =>
    {
        Print();
    });

    task.Wait();
    Console.Read();
}

public static void Print()
{
    Console.WriteLine("Comando executado pela task");
}

Podemos também aguardar a execução de todas as tarefas criadas e assim continuar nosso programa.

Veja o exemplo abaixo:

</pre>
Task[] tasks = new Task[3]
{
    Task.Factory.StartNew(() => MethodA()),
    Task.Factory.StartNew(() => MethodB()),
    Task.Factory.StartNew(() => MethodC())
};

Task.WaitAll(tasks);

Com a TPL podemos fazer coisas incríveis de forma simples, todo o trabalho de gerenciamento de execução e alocação de recursos ficam a cargo da TPL tornando nossa vida muito mais simples. Ao usar a TPL, você pode maximizar o desempenho do seu código enquanto se concentra no trabalho para o qual seu programa foi criado para realizar.

O que acharam ? Não deixem de comentar!

Abs e até a próxima.

Rafael Cruz

É desenvolvedor .NET há mais de 12 anos, certificado Microsoft desde de 2006, instrutor oficial Microsoft há 5 anos, Pós Graduado em Engenharia de Software pela UFRJ, suas certificações são Microsoft Certified Trainer, Microsoft Certified Solution Developer (Web, Application Lifecycle Management), Microsoft Certified Professional Developer, Microsoft Certified Tecnology Specialist.
Atualmente trabalha como arquiteto de sistema, escreve artigos no .NET Coders e no seu blog rafaelcruz.azurewebsites.net para compartilhar experiências na área de desenvolvimento Web, Aplicativos Móveis e Cloud Solutions.

Twitter LinkedIn 

Comentários

comentarios