Pergunta

Quando devo não usar o ThreadPool em .Net?

Parece que a melhor opção é usar um ThreadPool; nesse caso, por que não é a única opção?

Quais são suas experiências em torno disso?

Foi útil?

Solução

A única razão pela qual eu não usaria o ThreadPool para multithreading barato é se eu precisar…

  1. interagir com o método em execução (por exemplo, para eliminá-lo)
  2. executar código em um Tópico STA (isso aconteceu comigo)
  3. manter o thread ativo depois que meu aplicativo morrer (ThreadPool threads são threads de fundo)
  4. caso eu precise alterar a prioridade do Thread.Não podemos alterar a prioridade dos threads no ThreadPool, que por padrão é Normal.

P.S.: O artigo do MSDN "O pool de threads gerenciados" contém uma seção intitulada, "Quando não usar threads do pool de threads", com uma lista muito semelhante, mas um pouco mais completa, de possíveis motivos para não usar o pool de threads.

Existem muitos motivos pelos quais você precisaria pular o ThreadPool, mas se você não os conhece, então o ThreadPool deve ser bom o suficiente para você.

Alternativamente, veja o novo Estrutura de extensões paralelas, que contém algumas coisas interessantes que podem atender às suas necessidades sem a necessidade de usar o ThreadPool.

Outras dicas

@Eric, terei que concordar com Dean.Os tópicos são caros.Você não pode assumir que seu programa é o único em execução.Quando todos são gananciosos com recursos, o problema se multiplica.

Prefiro criar meus tópicos manualmente e controlá-los sozinho.Isso mantém o código muito fácil de entender.

Tudo bem quando é apropriado.Porém, se você precisar de vários threads de trabalho, tudo o que você fez foi tornar seu código mais complicado.Agora você precisa escrever código para gerenciá-los.Se você apenas usasse um pool de threads, obteria todo o gerenciamento de threads gratuitamente.E o pool de threads fornecido pela linguagem provavelmente será mais robusto, mais eficiente e com menos bugs do que qualquer coisa que você mesmo crie.

Thread t = new Thread(new ThreadStart(DoSomething));  
t.Start();  
t.Join();  

Espero que você normalmente tenha algum código adicional entre Start() e Join().Caso contrário, o thread extra será inútil e você desperdiçará recursos sem motivo.

As pessoas têm muito medo dos recursos usados ​​pelos threads.Nunca vi criar e iniciar um thread levar mais de um milissegundo.Não há limite rígido para o número de threads que você pode criar.O uso de RAM é mínimo.Depois de ter algumas centenas de threads, a CPU se torna um problema devido às mudanças de contexto; portanto, nesse ponto, você pode querer aprimorar seu design.

Um milissegundo é um longo tempo em hardware moderno.São 3 milhões de ciclos em uma máquina de 3GHz.E, novamente, você não é o único criando tópicos.Seus threads competem pela CPU junto com os threads de todos os outros programas.Se você não usa muitos threads, e outro programa também, então, juntos, vocês usaram muitos threads.

Sério, não torne a vida mais complexa do que precisa ser.Não use o pool de threads, a menos que precise de algo muito específico que ele oferece.

De fato.Não torne a vida mais complexa.Se o seu programa precisar de vários threads de trabalho, não reinvente a roda.Use o conjunto de threads.É por isso que está lá.Você criaria sua própria classe de strings?

Os pools de threads fazem sentido sempre que você tem o conceito de threads de trabalho.Sempre que você puder particionar facilmente o processamento em tarefas menores, cada uma das quais pode ser processada de forma independente, os threads de trabalho (e, portanto, um pool de threads) farão sentido.

Os pools de threads não fazem sentido quando você precisa de threads que executam ações totalmente diferentes e não relacionadas, que não podem ser consideradas "trabalhos";por exemplo, um thread para manipulação de eventos GUI, outro para processamento de back-end.Os pools de threads também não fazem sentido quando o processamento forma um pipeline.

Basicamente, se você tiver threads que iniciam, processam uma tarefa e encerram, um pool de threads é provavelmente a melhor opção.Caso contrário, o pool de threads não ajudará muito.

Para responder à discussão, eu acrescentaria que é melhor não usar um thread ThreadPool se você precisar garantir que seu thread começará a funcionar imediatamente.O número máximo de threads em pool de threads em execução é limitado por appdomain, portanto, seu trabalho pode ter que esperar se todos estiverem ocupados.Afinal, é chamado de "item de trabalho do usuário da fila".

Duas advertências, é claro:

  1. Você pode alterar o número máximo de threads agrupados no código, em tempo de execução, para que não haja nada que o impeça de verificar o número atual versus o número máximo e aumentar o máximo, se necessário.
  2. Criar um novo tópico acarreta sua própria penalidade de tempo - se vale a pena receber o golpe depende de suas circunstâncias.

Não estou falando como alguém com apenas conhecimento teórico aqui.Escrevo e mantenho aplicativos de alto volume que fazem uso pesado de multithreading, e geralmente não acho que o pool de threads seja a resposta correta.

Ah, argumento de autoridade - mas esteja sempre atento a pessoas que possam fazer parte da equipe do kernel do Windows.

Nenhum de nós estava discutindo o fato de que, se você tiver alguns requisitos específicos, o .NET ThreadPool pode não ser a coisa certa.O que nos opomos é à banalização dos custos da máquina de criação de um thread.

A despesa significativa de criação de um thread é a razão de ser do ThreadPool em primeiro lugar.Não quero que minhas máquinas sejam preenchidas com código escrito por pessoas que foram mal informadas sobre o custo de criação de um thread e não sabem, por exemplo, que isso faz com que um método seja chamado em cada DLL que é anexado ao processo (alguns dos quais serão criados por terceiros), e que pode muito bem aquecer uma carga de código que não precisa estar na RAM e quase certamente não precisa estar em L1.

O formato da hierarquia de memória em uma máquina moderna significa que “distrair” uma CPU é a pior coisa que você pode fazer, e todos que se preocupam com seu ofício devem trabalhar duro para evitá-lo.

Quando você vai executar uma operação que vai demorar muito, ou talvez um thread contínuo em segundo plano.Eu acho que você sempre pode aumentar a quantidade de threads disponíveis no pool, mas não faria sentido incorrer nos custos de gerenciamento de um thread que nunca será devolvido ao pool.

O MSDN tem uma lista de alguns motivos aqui:

http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

Existem vários cenários em que é apropriado criar e gerenciar seus próprios tópicos em vez de usar threads do pool de threads:

  • Você precisa de um thread em primeiro plano.
  • Você precisa que um thread tenha uma prioridade específica.
  • Você tem tarefas que fazem com que o thread fique bloqueado por longos períodos de tempo.O pool de threads possui um número máximo de threads; portanto, um grande número de threads bloqueados pode impedir que as tarefas iniciem.
  • Você precisa colocar threads em um apartamento de thread único.Todos os threads ThreadPool estão no apartamento multithread.
  • Você precisa ter uma identidade estável associada ao thread ou dedicar um thread a uma tarefa.

Os encadeamentos do Threadpool são apropriados para tarefas que atendem aos seguintes critérios:

  1. A tarefa não terá que gastar muito tempo esperando que algo aconteça
  2. Qualquer coisa que esteja aguardando a conclusão da tarefa provavelmente estará aguardando a conclusão de muitas tarefas, portanto, sua prioridade de agendamento não poderá afetar muito as coisas.

Usar um thread de pool de threads em vez de criar um novo economizará um tempo significativo, mas limitado.Se esse tempo for significativo em comparação com o tempo necessário para executar uma tarefa, uma tarefa de conjunto de encadeamentos provavelmente será apropriada.Quanto maior o tempo necessário para executar uma tarefa, porém, menor será o benefício de usar o threadpool e maior será a probabilidade da tarefa impedir a eficiência do threadpool.

@Érico

@Derek, não concordo exatamente com o cenário que você usa como exemplo.Se você não sabe exatamente o que está sendo executado em sua máquina e exatamente quantos threads, identificadores, tempo de CPU, RAM, etc., seu aplicativo usará sob uma certa quantidade de carga, você está com problemas.

Você é o único cliente-alvo dos programas que escreve?Caso contrário, você não pode ter certeza sobre a maior parte disso.Geralmente, quando você escreve um programa, você não tem ideia se ele será executado de maneira eficaz sozinho ou se será executado em um servidor da Web que está sendo atacado por um ataque DDOS.Você não pode saber quanto tempo de CPU terá.

Supondo que o comportamento do seu programa mude com base na entrada, é raro saber exatamente quanta memória ou tempo de CPU seu programa consumirá.Claro, você deve ter uma boa ideia de como seu programa se comportará, mas a maioria dos programas nunca é analisada para determinar exatamente quanta memória, quantos identificadores, etc.será usado, porque uma análise completa é cara.Se você não estiver escrevendo software em tempo real, a recompensa não valerá o esforço.

Em geral, afirmar que sabe exatamente como seu programa se comportará é absurdo, e afirmar que sabe tudo sobre a máquina é ridículo.

E para ser sincero, se você não sabe exatamente qual método deve usar:threads manuais, pool de threads, delegados e como implementá-los para fazer exatamente o que seu aplicativo precisa, você está com problemas.

Não discordo totalmente, mas realmente não vejo como isso é relevante.Este site está aqui especificamente porque os programadores nem sempre têm todas as respostas.

Se seu aplicativo for complexo o suficiente para exigir a limitação do número de threads que você usa, você quase sempre não vai querer mais controle do que o que a estrutura oferece?

Não.Se eu precisar de um pool de threads, usarei aquele fornecido, a menos e até que eu descubra que não é suficiente.Não assumirei simplesmente que o conjunto de threads fornecido é insuficiente para minhas necessidades sem confirmar que esse é o caso.

Não estou falando aqui como alguém com conhecimento apenas teórico.Eu escrevo e mantenho aplicativos de alto volume que fazem uso intenso de multithreading e geralmente não considero o pool de threads a resposta correta.

A maior parte da minha experiência profissional foi com programas multithreading e multiprocessamento.Muitas vezes também precisei lançar minha própria solução.Isso não significa que o pool de threads não seja útil ou apropriado em muitos casos.O pool de threads é construído para lidar com threads de trabalho.Nos casos em que vários threads de trabalho são apropriados, o conjunto de threads fornecido geralmente deve ser a primeira abordagem.

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