Parallel.ForEach: Processamento Paralelo em C# Explicado

Processamento paralelo é como abrir caixas extras no supermercado: em vez de uma fila gigante, dividimos o trabalho para🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)Descubra como automatizar repetições em C# utilizando loops for e while com exemplos práticos que evitam erros e otimizam seu código. Aprenda mais! terminar mais rápido! Neste artigo, vamos explorar como o Parallel.ForEach no C# permite realizar tarefas de forma paralela, melhorando a performance🔄 StringBuilder: Quando Concatenar Strings Vira um Pesadelo!🔄 StringBuilder: Quando Concatenar Strings Vira um Pesadelo!Descubra como o StringBuilder otimiza a concatenação em C#, evitando desperdício de memória e melhorando a performance das aplicações. Veja exemplos práticos! de maneira eficiente sem precisar escrever código complexo para gerenciar threads. Vamos entender o que é, como funciona, e ver exemplos práticos do dia a dia.

📌 Índice🔗

1. O que é Parallel.ForEach e📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. por que usar?

2. Como Funciona na Prática

3. Exemplo de Código

4. Gerenciando Concorrência e Erros🎲 Desafio: Crie um Sistema de Login com Tratamento de Erros Robusto!🎲 Desafio: Crie um Sistema de Login com Tratamento de Erros Robusto!Aprenda a criar um sistema de login robusto em C#, com tratamento de erros adequado, validação e segurança para evitar vulnerabilidades.

5. Dicas de Otimização⏱️ Testes de Performance: Garanta Velocidade Além da Funcionalidade!⏱️ Testes de Performance: Garanta Velocidade Além da Funcionalidade!Descubra como medir, diagnosticar e otimizar performance em aplicações .NET com dicas práticas e ferramentas essenciais para devs.

6. Por que paralelizar🧩 PLINQ: Paralelize Consultas e Acelere em 10x!🧩 PLINQ: Paralelize Consultas e Acelere em 10x!Descubra como o PLINQ acelera consultas em grandes volumes de dados utilizando múltiplos núcleos. Guia completo para otimizar operações em .NET.? O problema do sequencial

7. Anatômia do Parallel.ForEach

8. Controlando o Paralelismo: grau, cancelamento

9. Erros comuns🔏 Criptografia Assimétrica: Domine RSA e Troca de Chaves!🔏 Criptografia Assimétrica: Domine RSA e Troca de Chaves!Descubra como a criptografia assimétrica protege a troca de chaves e garante segurança em sistemas digitais usando RSA, C# e práticas recomendadas. e Armadilhas

10. Caso Real: Processamento de Imagens🧠 Memory Management Avançado: Domine Span<T> e MemoryMarshal!🧠 Memory Management Avançado: Domine Span<T> e MemoryMarshal!Transforme seu código C# usando Span<T> e MemoryMarshal para manipulação eficiente de memória, reduzindo alocações desnecessárias e elevando a performance. em Lote

🐢 O que é Parallel.ForEach e por que usar?🔗

O Parallel.ForEach é um método🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. que permite iterar sobre coleções de forma paralela, dividindo o trabalho entre vários threads de maneira automática. Diferentemente de um loop tradicional (for🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)Descubra como automatizar repetições em C# utilizando loops for e while com exemplos práticos que evitam erros e otimizam seu código. Aprenda mais! ou foreach), o tempo total de processamento pode cair drasticamente, principalmente quando📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. temos várias tarefas que podem rodar em paralelo (e sem depender uma da outra).

Alguns cenários📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. onde ele se encaixa muito bem:

  • Processar centenas ou milhares de arquivos de log.
  • Aplicar transformações em imagens simultaneamente.
  • Fazer cálculos matemáticos em lote, como análises estatísticas.

Ele faz parte do namespace System.Threading.Tasks, que fornece recursos📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!Descubra os fundamentos do REST e boas práticas para criar APIs simples, escaláveis e eficientes. Domine métodos HTTP e status codes com exemplos práticos. para programação paralela. O porquê de usar é simples: com o aumento🔢 Operadores Aritméticos: Faça Cálculos como uma Calculadora Humana!🔢 Operadores Aritméticos: Faça Cálculos como uma Calculadora Humana!Aprenda a dominar operadores aritméticos em C# com exemplos práticos, técnicas de cálculo e dicas para evitar erros e maximizar resultados. de núcleos (cores) e threads nos processadores atuais, é um desperdício não aproveitar toda essa capacidade de forma eficiente.

🔧 Como Funciona na Prática🔗

O Parallel.ForEach divide a coleção em “partes” e distribui essas partes para execução em threads diferentes. Você não precisa gerenciar manualmente as threads; o tempo de vida🧠 Variáveis em C#: Onde os Dados Ganham Vida (e Nome!)🧠 Variáveis em C#: Onde os Dados Ganham Vida (e Nome!)Descubra como as variáveis em C# funcionam, com exemplos do mundo real, boas práticas de nomeação e dicas para otimizar seu código. e o controle são administrados pela biblioteca interna do .NET.

Em alto nível, ele executa algo como:

1. Cria um “scheduler” que decide em quantas partes dividir a coleção.

2. Para🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)Descubra como automatizar repetições em C# utilizando loops for e while com exemplos práticos que evitam erros e otimizam seu código. Aprenda mais! cada pedaço, chama a ação que você definiu.

3. Garante (na configuração🚀 Scale Out com Redis: Atenda Milhões de Conexões!🚀 Scale Out com Redis: Atenda Milhões de Conexões!Integre o Redis com SignalR no .NET e distribua mensagens entre servidores, alcançando escalabilidade e alta performance em tempo real. padrão) que cada elemento seja processado uma única vez.

Essa ação pode ser qualquer método ou expressão lambda🚀 Expressões Lambda: Sintaxe Enxuta para Código Poderoso!🚀 Expressões Lambda: Sintaxe Enxuta para Código Poderoso!Aprenda a usar expressões lambda no C# para reduzir verbosidade e escrever códigos limpos com exemplos práticos e aplicações em LINQ, delegates e eventos. que receba o item atual da coleção para processamento.

📄 Exemplo de Código🔗

Suponha que temos uma lista📦 List<T>: Dinamismo além dos Arrays!📦 List<T>: Dinamismo além dos Arrays!Descubra como utilizar List<T> em C# de forma eficiente. Aprenda a criar, manipular e otimizar listas para diferentes cenários com exemplos práticos. de números e queremos fazer uma operação “pesada” em cada valor (por exemplo, simular uma demora para cada elemento):

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
    static void Main()
    {
        List<int> numeros = new List<int>();
        for (int i = 0; i < 10; i++)
        {
            numeros.Add(i);
        }
        Parallel.ForEach(numeros, numero =>
        {
            // Simula uma operação pesada
            Console.WriteLine($"Processando: {numero}");
            // Por exemplo, poderíamos colocar:
            // Task.Delay(1000).Wait();
        });
        Console.WriteLine("Concluído!");
    }
}

O método🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!🧠 Métodos em C#: Como Criar Funções que Não São Só Enfeites!Otimize seu código em C# com métodos inteligentes. Aprenda práticas de reutilização, sobrecarga e escopo para melhorar a clareza e a eficiência. Parallel.ForEach vai processar cada item em paralelo, respeitando a quantidade🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. de threads que o .NET julgar ideal. Em máquinas com mais núcleos, a tendência é que o loop acelere bastante.

🛠️ Gerenciando Concorrência e Erros🔗

Quando há vários threads trabalhando simultaneamente, precisamos ter cuidado se houver acesso compartilhado a recursos como arquivos ou variáveis🧠 Variáveis em C#: Onde os Dados Ganham Vida (e Nome!)🧠 Variáveis em C#: Onde os Dados Ganham Vida (e Nome!)Descubra como as variáveis em C# funcionam, com exemplos do mundo real, boas práticas de nomeação e dicas para otimizar seu código. estáticas. Alguns pontos de atenção:

1. Variáveis🧠 Variáveis em C#: Onde os Dados Ganham Vida (e Nome!)🧠 Variáveis em C#: Onde os Dados Ganham Vida (e Nome!)Descubra como as variáveis em C# funcionam, com exemplos do mundo real, boas práticas de nomeação e dicas para otimizar seu código. compartilhadas: Se você escrever e ler dados numa mesma variável🧠 Variáveis em C#: Onde os Dados Ganham Vida (e Nome!)🧠 Variáveis em C#: Onde os Dados Ganham Vida (e Nome!)Descubra como as variáveis em C# funcionam, com exemplos do mundo real, boas práticas de nomeação e dicas para otimizar seu código. global ou estática, há risco de race conditions.

2. Lock🚫 Deadlocks: O que São e Como Fugir Deles!🚫 Deadlocks: O que São e Como Fugir Deles!Descubra o que são deadlocks em C#, aprenda com exemplos práticos e estratégias para evitar bloqueios que travam suas aplicações e comprometer performance. e sincronização: Caso realmente precise compartilhar recursos📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!📡 RESTful 101: Princípios que Todo Dev API Precisa Saber!Descubra os fundamentos do REST e boas práticas para criar APIs simples, escaláveis e eficientes. Domine métodos HTTP e status codes com exemplos práticos., considere usar mecanismos como lock🚫 Deadlocks: O que São e Como Fugir Deles!🚫 Deadlocks: O que São e Como Fugir Deles!Descubra o que são deadlocks em C#, aprenda com exemplos práticos e estratégias para evitar bloqueios que travam suas aplicações e comprometer performance..

3. Tratamento de exceções💥 Try/Catch: Domine Exceções antes que Elas Dominem Você!💥 Try/Catch: Domine Exceções antes que Elas Dominem Você!Descubra como tratar exceções em C# com práticas eficientes utilizando try/catch. Aprenda a gerenciar erros e aumentar a robustez do seu código.: Se algo der errado dentro do loop, a exceção💥 Try/Catch: Domine Exceções antes que Elas Dominem Você!💥 Try/Catch: Domine Exceções antes que Elas Dominem Você!Descubra como tratar exceções em C# com práticas eficientes utilizando try/catch. Aprenda a gerenciar erros e aumentar a robustez do seu código. pode ser agregada em um objeto AggregateException. Sempre trate isso para🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)Descubra como automatizar repetições em C# utilizando loops for e while com exemplos práticos que evitam erros e otimizam seu código. Aprenda mais! entender quais iterações falharam.

A ideia é manter o loop🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)🔄 Loops em C#: Repita Tarefas sem Enlouquecer (Com for e while!)Descubra como automatizar repetições em C# utilizando loops for e while com exemplos práticos que evitam erros e otimizam seu código. Aprenda mais! o mais independente possível, reduzindo a necessidade de controle manual de concorrência.

🎛️ Dicas de Otimização🔗

O segredo é testar e📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. avaliar se o loop paralelo realmente traz vantagens na tarefa🤝 GitHub Básico: Versionamento para Iniciantes!🤝 GitHub Básico: Versionamento para Iniciantes!Descubra como o GitHub facilita colaboração, versionamento e organização de código com este tutorial prático e essencial para desenvolvedores iniciantes. que você está desenvolvendo.

🐢 O Pesadelo do Processamento Sequencial🔗

Imagine processar 10,000 imagens em um sistema de upload:

foreach (var image in images)
{
    ApplyFilters(image); // 200ms por imagem → 33 minutos total!
}

Resultado: Usuário esperando meia hora! Com paralelismo, dividimos o trabalho entre núcleos do CPU.

🔧 Anatomia do Parallel.ForEach🔗

Parallel.ForEach(
    source: images,                  // Coleção a processar
    body: image => ApplyFilters(image) // Ação para cada item
);

Fluxo Interno:

1. Divide a lista📦 List<T>: Dinamismo além dos Arrays!📦 List<T>: Dinamismo além dos Arrays!Descubra como utilizar List<T> em C# de forma eficiente. Aprenda a criar, manipular e otimizar listas para diferentes cenários com exemplos práticos. em partes (ex: 4 núcleos → 4 partes)

2. Processa partes simultaneamente em threads separadas

3. Sincroniza resultados ao final

🎛️ Afinando o Paralelismo🔗

Definindo Grau Máximo de Paralelismo

var options = new ParallelOptions { MaxDegreeOfParallelism = 4 };
Parallel.ForEach(images, options, image =>
{
    // Processamento com no máximo 4 threads
});

Cancelamento com CancellationToken

var cts = new CancellationTokenSource();
Parallel.ForEach(images, new ParallelOptions { CancellationToken = cts.Token }, image =>
{
    if (image.IsCorrupted) cts.Cancel();
    Process(image);
});

💥 Armadilhas Comuns (e Como Evitar)🔗

Variáveis Compartilhadas

int totalProcessed = 0;
Parallel.ForEach(images, image =>
{
    totalProcessed++; // Race condition!
});

Solução: Use Interlocked.Increment(ref totalProcessed);

Excesso de Paralelismo

🖼️ Caso Real: Processador de Imagens🔗

Objetivo: Aplicar filtros🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!🎲 Desafio: Analise Dados de Vendas com LINQ e Coleções!Aprenda a usar coleções e LINQ em C# para analisar vendas, filtrar dados e extrair insights estratégicos que otimizem decisões e impulsionem seu negócio. em 10,000 imagens usando 80% da CPU.

var options = new ParallelOptions
{
    MaxDegreeOfParallelism = (int)(Environment.ProcessorCount * 0.8)
};
Parallel.ForEach(images, options, image =>
{
    var thumbnail = GenerateThumbnail(image);
    UploadToCloud(thumbnail); // Cuidado: IO-bound! Melhor usar async/await
});

Observações:

📊 Tabela Comparativa: Sequencial vs. Paralelo🔗

MétricaforeachParallel.ForEach
Tempo (10k itens)33 min~5 min (6 núcleos)
Uso CPU12%90%+
ComplexidadeBaixaMédia
Risco de BugsBaixoAlto (thread-safety)

🚀 Conclusão🔗

O Parallel.ForEach é uma ferramenta poderosa, mas📊 Behavior-Driven Development: Testes que Todo Mundo Entende!📊 Behavior-Driven Development: Testes que Todo Mundo Entende!Descubra como o BDD transforma testes em linguagens acessíveis. Aprenda a usar SpecFlow em C# para criar testes claros, colaborativos e sem ambiguidades. exige cuidado:

// Bônus: Parallel.ForEach com resultados agregados
var results = new ConcurrentBag<string>();
Parallel.ForEach(urls, url =>
{
    var data = DownloadData(url);
    results.Add(data);
});

Em resumo🌐 LinkedIn para Devs .NET: Perfil que Atrai Recrutadores!🌐 LinkedIn para Devs .NET: Perfil que Atrai Recrutadores!Aprenda a otimizar seu perfil LinkedIn com dicas essenciais para devs .NET. Conquiste oportunidades e destaque suas habilidades!, Parallel.ForEach simplifica o processamento paralelo de coleções, aproveitando a capacidade multinúcleo dos processadores de forma automática. Para muita gente, é o caminho mais rápido para paralelizar🧩 PLINQ: Paralelize Consultas e Acelere em 10x!🧩 PLINQ: Paralelize Consultas e Acelere em 10x!Descubra como o PLINQ acelera consultas em grandes volumes de dados utilizando múltiplos núcleos. Guia completo para otimizar operações em .NET. uma tarefa iterativa sem precisar gerenciar a complexidade de threads manualmente.

Autor: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.

Referências🔗

Compartilhar artigo

Artigos Relacionados