Trabalhando com Filas de Tarefas em C#: Para Iniciantes
\n\nNo desenvolvimento moderno, frequentemente surge a necessidade de processar várias tarefas sem bloquear o thread principal da aplicação. Imagine um servidor web que precisa responder a centenas de usuários simultaneamente, ou um serviço em segundo plano processando uploads de arquivos. Nessas situações, a fila de tarefas (task queue) vem ao resgate — uma das estruturas de dados e padrões de programação fundamentais.
\n\nNeste artigo, vamos explorar com exemplos práticos como as filas de tarefas funcionam em C# (.NET), começando pelas classes básicas até soluções thread-safe para aplicações multithread.
\n\nO que é uma Fila de Tarefas e para que Serve?
\n\nUma fila (Queue) é uma estrutura de dados que opera pelo princípio FIFO (First In, First Out): o primeiro elemento adicionado será o primeiro a ser processado. No contexto de tarefas, isso significa que podemos colocar uma tarefa na fila e processá-la mais tarde, quando os recursos estiverem disponíveis.
\n\nPrincipais cenários de uso de filas de tarefas:
\n- \n
- Processamento em segundo plano (envio de e-mail, geração de relatórios) \n
- Balanceamento de carga (distribuição de tarefas entre threads de trabalho) \n
- Buffer de requisições (quando o sistema não pode processar todas as requisições instantaneamente) \n
- Logging assíncrono (gravação de logs sem desacelerar a aplicação principal) \n
Classe Básica Queue<T> em C#
\n\nNo .NET, existe a classe embutida Queue<T> do namespace System.Collections.Generic. Vamos ver um exemplo simples:
using System;\nusing System.Collections.Generic;\n\npublic class SimpleQueueExample\n{\n public static void Main()\n {\n // Criando uma fila de strings\n Queue<string> taskQueue = new Queue<string>();\n\n // Adicionando tarefas\n taskQueue.Enqueue("Enviar e-mail para o cliente");\n taskQueue.Enqueue("Gerar relatório");\n taskQueue.Enqueue("Atualizar cache");\n\n Console.WriteLine($"Quantidade de tarefas na fila: {taskQueue.Count}");\n\n // Processando tarefas em ordem\n while (taskQueue.Count > 0)\n {\n string task = taskQueue.Dequeue();\n Console.WriteLine($"Processando: {task}");\n }\n\n Console.WriteLine($"Fila vazia: {taskQueue.Count == 0}");\n }\n}\n\nPrincipais métodos de Queue<T>:
- \n
Enqueue(T item)— adiciona um elemento ao final da fila \n Dequeue()— remove e retorna o elemento do início da fila \n Peek()— retorna o primeiro elemento sem removê-lo \n Count— quantidade de elementos na fila \n
Importante: Queue<T> não é thread-safe. Se várias threads lerem e escreverem na fila simultaneamente, ocorrerão erros. Para cenários multithread, use ConcurrentQueue<T>.
Fila Thread-Safe: ConcurrentQueue<T>
\n\nEm aplicações reais, filas de tarefas quase sempre são usadas em contexto multithread. Para isso, no .NET existe ConcurrentQueue<T> do namespace System.Collections.Concurrent.
using System;\nusing System.Collections.Concurrent;\nusing System.Threading.Tasks;\n\npublic class ConcurrentQueueExample\n{\n public static void Main()\n {\n ConcurrentQueue<string> taskQueue = new ConcurrentQueue<string>();\n\n // Tarefa 1: adicionando elementos (Producer)\n Task producer = Task.Run(() =>\n {\n for (int i = 1; i <= 10; i++)\n {\n taskQueue.Enqueue($"Tarefa #{i}");\n Console.WriteLine($"Adicionada tarefa #{i}");\n