Multi-threading em C# (programação concorrente)

Marcio Nizzola
5 min readMay 6, 2021

Uma das melhores coisas disponíveis no mundo da tecnologia é a possibilidade de executar múltiplas tarefas simultaneamente.

No início da computação nos meados dos anos 90, tínhamos sistemas operacionais que não permitiam a execução simultânea de tarefas!

Imaginem um mundo onde em seu computador, na hora de imprimir, ele parava de responder até que a impressão fosse concluída, ou se disparássemos uma outra tarefa que tinha prioridade, a sua impressão parava para que o computador pudesse concluir o outro trabalho.

Graças aos avanços tecnológicos hoje podemos ouvir música, trabalhar, fazer downloads, baixar arquivos tudo simultaneamente !!

Da mesma forma, podemos criar software onde em seu interior processos sejam executados paralelamente e concluam as tarefas mais rápido !

A linguagem C# tem o recurso multi-threading, que permite a execução de múltiplos processos em paralelo, neste post iremos demonstrar através de um exemplo simples como é que ele funciona !

Multi-threading em C#

Threads são processos leves que atuam como um caminho pelo qual um processo pode ser executado. Cada processo / aplicativo é executado por padrão com um único thread. Todo o código do aplicativo é executado sequencialmente em um único thread.

Os aplicativos multi-thread introduziram a capacidade de processar o código independente simultaneamente em mais de um thread. O multi-threading ajuda a reduzir o tempo de execução e também faz uso da potência da CPU em um nível ideal.

O namespace System.Threading contém as classes e a interface que permitem o multi-threading em um aplicativo.

Ciclo de Vida do Tópico

Aqui está o ciclo de vida de um segmento -

Unstarted State (Estado não iniciado) — estado no qual a instância do encadeamento é criada, mas ainda não começou a ser executada. Em outras palavras, o método Start () do Thread não está sendo chamado.

Ex: — var thread = new Thread ();

Ready State (Estado Pronto) — Um encadeamento que está pronto para ser executado está em um estado executável / pronto. Isso significa que uma instância do encadeamento é criada e está pronta para ser executada a qualquer momento.

Running State (Estado de execução) — como o nome indica, o encadeamento em execução é considerado em um estado de execução.

Non-Runnable State (Estado não executável) — Estado no qual o encadeamento não é executável. Abaixo estão alguns estados que são considerados não executáveis ​​quando,

  • O método Sleep () do thread está ativo
  • O método Wait () do thread está ativo
  • O método Suspend () do thread é chamado
  • Esperando por operações de I / O

Dead State (estado morto) — Quando o thread conclui a tarefa atribuída a ele, ele é considerado em um estado morto.

Métodos e Propriedades disponíveis

Os métodos mais utilizados e que alteram o estado de uma thread são:

  • public void Start () — Este método é invocado para iniciar um thread.
  • public static void Sleep (int millisecondsTimeout) — Este método é usado para suspender o thread atual pelo período de milissegundos definido. Como o método é estático, ele é invocado diretamente com o nome da classe (Thread.Sleep (2000)).
  • public void Suspend () — Suspende o tópico. Não afeta se for chamado quando o encadeamento já estiver suspenso. Além disso, ele lança uma exceção quando invocado antes de iniciar ou depois que o encadeamento está morto.
  • public void Resume () — Retoma o tópico suspenso. Ele lança uma exceção quando chamado e o encadeamento não foi iniciado ou quando não está suspenso.
  • public void Abort () — Terminou o thread de chamada.

Propriedades que são acessadas com frequência.

  • public string Name {get; set; } — Fornece o nome do objeto thread. Além disso, os usuários podem atribuir nomes de encadeamento em tempo de execução.
  • public bool IsAlive {get; } — fornece se o objeto thread está ativo. Ele retorna verdadeiro ou falso. É uma propriedade somente leitura.
  • public ThreadState ThreadState {get; } — fornece o estado do thread. Ele retorna o estado com ThreadState como o tipo de retorno.
  • public ThreadPriority Priority {get; set; } — Os usuários podem atribuir e ler a prioridade da instância do thread usando esta propriedade. A prioridade pode ser definida com o tipo ThreadPriority (enum).

Então, agora que a parte teórica vamos ao que interessa !

Aplicação prática multi-thread

Para exemplificar todos estes conceitos na práticas, então vamos criar uma aplicação do tipo Console !

Abra seu Visual Studio e vamos começar, escolhendo o tipo de aplicação:

Feito isso, escolha a pasta e crie o projeto.

Assim que o Visual Studio exibir nosso projeto, iremos criar 2 métodos nele e referenciá-los.

Nessa primeira etapa, criamos 2 métodos para serem executados em uma sequência, antes de implementarmos as Threads.

Ao executar, o resultado é o seguinte:

Notem que o processo B só começa quando o processo A termina, ou seja, uma única linha de execução foi disparada no programa.

Implementando as Threads

Agora, vamos modificar o código e colocar as Threads para funcionar.

Ao executar….

Muita calma nessa hora, como são processos simples eles foram executados instantaneamente e assim continuaram em sequência.

Vamos colocar um pouco de emoção nesse exemplo, agora vou colocar uma carga a mais no processo A, fazendo com que ele demore mais a execução.

E agora, vamos executar novamente

Então podemos ver que de forma paralela eles puderam executar lado a lado e tudo aconteceu de forma normal, gerenciados pela aplicação sem maiores sacrifícios.

Numa situação real, podemos ter processos que buscam informações em Bancos de Dados, Acessam API´S Externas, e poderiam rodar paralelamente para que as respostas possam ser disponibilizadas muito mais rapidamente.

Outra aplicação é quebrar alguns processamentos de dados massivos em múltiplas Threads e realizar tarefas mais rapidamente.

Muito cuidado ao utilizar Listas em Threads, existem tipos “Thread-Safe” que foram feitos para suportar operações Multi-Threading !!

Referências:

Thread Classe (System.Threading) | Microsoft Docs

Thread-Safe Collections | Microsoft Docs

--

--

Marcio Nizzola

Microsoft MVP | Software Architect na CI&T | Prof. da Etec Itu | Membro Fundador da Comunidade Itu Developers.