Qual é a melhor maneira de passar dados entre threads simultâneos em .NET?
-
01-07-2019 - |
Pergunta
Eu tenho dois tópicos, é preciso pesquisar um monte de recursos estáticos separados procurando atualizações. As outras necessidades de cada um para obter os dados e armazená-lo no banco de dados. Como pode enfiar 1 fio tell 2 que há algo de processo?
Solução
Se as partes de dados são independentes, em seguida, tratar os pedaços de dados como itens de trabalho a serem processados ??por um pool de threads. Use o pool de threads e QueueUserWorkItem
para enviar os dados para o segmento (s). Você deve obter uma melhor escalabilidade usando um pool de threads simétricas e limitando a quantidade de sincronização que tem que ocorrer entre os produtores e consumidores (s).
Por exemplo (a partir de MSDN ):
TaskInfo ti = new TaskInfo("This report displays the number {0}.", 42);
// Queue the task and data.
if (ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc), ti)) {
Console.WriteLine("Main thread does some work, then sleeps.");
// If you comment out the Sleep, the main thread exits before
// the ThreadPool task has a chance to run. ThreadPool uses
// background threads, which do not keep the application
// running. (This is a simple example of a race condition.)
Thread.Sleep(1000);
Console.WriteLine("Main thread exits.");
}
else {
Console.WriteLine("Unable to queue ThreadPool request.");
}
// The thread procedure performs the independent task, in this case
// formatting and printing a very simple report.
//
static void ThreadProc(Object stateInfo) {
TaskInfo ti = (TaskInfo) stateInfo;
Console.WriteLine(ti.Boilerplate, ti.Value);
}
Outras dicas
Eu uso Monitor.Wait / Pulse em uma fila de itens de trabalho.
Será que a "loja no DB" thread sempre precisa estar em execução? Parece que talvez a melhor opção (se possível) seria ter o spin fio polling-se outro segmento para fazer o salvamento. Dependendo do número de threads que está sendo criado, porém, pode ser que tendo o primeiro polling uso tópico ThreadPool.QueueUserWorkItem () pode ser a rota mais eficiente.
Para obter mais eficiência, ao salvar o banco de dados, eu usaria async I / O no DB em vez dos métodos de sincronização.
A qualquer momento você pode ficar longe de ter que comunicar-se diretamente entre dois threads, você deve. Ter que jogar juntos algumas primitivas de sincronização, seu código não será tão fácil de depurar e poderiam introduzir algumas condições de corrida muito sutis que causam "uma vez em um milhão de execução" bugs do tipo (que estão longe de diversão para encontrar / fix).
Se o segundo segmento sempre precisa ser executado, deixe-nos saber por que com mais algumas informações e podemos voltar com uma resposta mais aprofundada.
Boa sorte!
Eu, pessoalmente, teria acontecimentos fio 1 Levante qual thread 2 pode responder. Os fios podem ser ligados até os eventos apropriados pelo processo de controle que inicia ambas as linhas.