Pergunta

Estou escrevendo um aplicativo que precisará usar Timers, mas potencialmente muitos deles.Quão escalável é o System.Threading.Timer aula?A documentação apenas diz que é "leve", mas não explica mais nada.Esses temporizadores são sugados para um único encadeamento (ou conjunto de encadeamentos muito pequeno) que processa todos os retornos de chamada em nome de um Timer, ou cada um Timer tem seu próprio tópico?

Acho que outra maneira de reformular a pergunta é:Como é System.Threading.Timer implementado?

Foi útil?

Solução

Digo isso em resposta a muitas perguntas:Não esqueça que o código-fonte (gerenciado) da estrutura está disponível.Você pode usar esta ferramenta para obter tudo: http://www.codeplex.com/NetMassDownloader

Infelizmente, neste caso específico, grande parte da implementação está em código nativo, então você não consegue olhar para ela...

Eles definitivamente usam threads de pool em vez de threads por temporizador.

A maneira padrão de implementar uma grande coleção de temporizadores (que é como o kernel faz isso internamente, e eu suspeito que seja indiretamente como sua grande coleção de temporizadores termina) é manter a lista ordenada por tempo até a expiração - então o o sistema só precisa se preocupar em verificar o próximo cronômetro que irá expirar, não a lista inteira.

Aproximadamente, isso fornece O(log n) para iniciar um cronômetro e O(1) para processar cronômetros em execução.

Editar:Estou olhando o livro de Jeff Richter.Ele diz (de Threading.Timer) que usa um único thread para todos os objetos Timer, esse thread sabe quando será o próximo timer (ou seja,como acima) é devido e chama ThreadPool.QueueUserWorkItem para os retornos de chamada conforme apropriado.Isso tem o efeito de que, se você não terminar de atender um retorno de chamada em um cronômetro antes do vencimento do próximo, seu retorno de chamada entrará novamente em outro thread do pool.Portanto, em resumo, duvido que você veja um grande problema em ter muitos temporizadores, mas poderá sofrer exaustão do pool de threads se um grande número deles estiver disparando ao mesmo tempo e/ou seus retornos de chamada estiverem lentos.

Outras dicas

Acho que você pode querer repensar seu design (isto é, se você mesmo tiver controle sobre o design).Se você estiver usando tantos temporizadores que isso seja realmente uma preocupação para você, há claramente algum potencial de consolidação aí.

Aqui está um bom artigo da MSDN Magazine de alguns anos atrás que compara as três classes de timer disponíveis e fornece algumas dicas sobre suas implementações:

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

Consolide-os.Criar um temporizador serviço e pedir isso para os temporizadores.Ele só precisará manter 1 ativo temporizador (para a próxima chamada devida)...

Para que isso seja uma melhoria em relação à criação de muitos objetos Threading.Timer, você deve assumir que não é exatamente o que Threading.Timer já está fazendo internamente.Eu estaria interessado em saber como você chegou a essa conclusão (não desmontei as partes nativas do framework, então você pode estar certo).

^^ como DannySmurf diz:Consolide-os.Crie um serviço de cronômetro e peça isso para os cronômetros.Será necessário apenas manter 1 cronômetro ativo (para a próxima chamada) e um histórico de todas as solicitações de cronômetro e recalcular isso em AddTimer() / RemoveTimer().

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top