Eu tenho uma classe que contém um arquivo BlockingCollection<Task>
usado para enfileirar uma série de tarefas para serem executadas em ordem (FIFO).
A fila em si é iniciada em uma tarefa separada de longa execução.
public class TaskQueue
{
private readonly BlockingCollection<Task> _queue = new BlockingCollection<Task>();
public TaskQueue()
{
Task.Factory.StartNew(() =>
{
ProcessQueue();
}, TaskCreationOptions.LongRunning);
}
private async Task ProcessQueue()
{
foreach (var task in _queue.GetConsumingEnumerable())
await task;
}
...
}
Quando o aplicativo é iniciado, crio muitas instâncias, TaskQueue
pois preciso de filas diferentes para diferentes componentes do aplicativo.
O problema que estou vendo é que, embora ProcessQueue()
seja iniciado em uma tarefa LongRunning .NET Long Running Task
, após a primeira espera da tarefa, ela retorna, ou .NET ThreadPool Worker
seja, não é mais uma tarefa de longa execução.
Isso resulta em todas as instâncias TaskQueue.ProcessQueue
terminando .NET ThreadPool Workers
(após a primeira espera), o que faz com que o aplicativo fique muito lento para iniciar novas tarefas, pois atingiu o número máximo de execuções simultâneas .NET ThreadPool Workers
(acredito que isso esteja definido como o número de núcleos que a máquina possui, no meu caso 8), após os quais ela só criará novos .NET ThreadPool Workers
a cada segundo ou mais.
Então minhas perguntas são:
- Existe uma maneira de retornar a uma tarefa de longa duração?
- Ou devo apenas substituir
Task.Factory.StartNew
por um novo Thread? que acredito que resolverá o problema, mas não tenho certeza se existe uma maneira melhor.
Sim, em primeiro lugar, não abandonando a tarefa de longa duração. Você pode alterar a assinatura do
ProcessQueue
retornovoid
em vez deTask
assim:Dessa forma, a
LongRunning
tarefa alternará entre esperar para consumir uma tarefa e esperar que a tarefa consumida seja concluída. O mesmo thread fará toda a espera.Aliás, tanto a
async
versão original doProcessQueue
, quanto avoid
versão sugerida aqui, não estão fazendo nada de construtivo. Eles não estão processando nada, estão apenas esperando. Presumo que você omitiu a parte "processo" do método, para manter o exemplo simples. Caso contrário,ProcessQueue
seria apenas um exercício de futilidade.