Vejo muitas pessoas em postagens de blog e aqui no SO evitando ou aconselhando contra o uso da Thread
classe em versões recentes do C # (e, claro, 4.0+, com a adição de Task
& amigos). Mesmo antes, havia debates sobre o fato de que a funcionalidade de um thread simples e antigo pode ser substituída em muitos casos pela ThreadPool
classe.
Além disso, outros mecanismos especializados estão tornando a Thread
classe menos atraente, como Timer
a substituição do combo feio Thread
+ Sleep
, enquanto para GUIs temosBackgroundWorker
, etc.
Ainda assim, o Thread
parece ser um conceito muito familiar para algumas pessoas (inclusive eu), pessoas que, quando confrontadas com uma tarefa que envolve algum tipo de execução paralela, passam diretamente a usar o bom e velhoThread
classe. Ultimamente, tenho me perguntado se é hora de corrigir meus hábitos.
Portanto, minha pergunta é: há casos em que é necessário ou útil usar um Thread
objeto simples e antigo em vez de uma das construções acima?
fonte
64.5k
. Uma exibição bastante impressionanteRespostas:
A classe Thread não pode se tornar obsoleta porque obviamente é um detalhe de implementação de todos os outros padrões que você mencionou.
Mas essa não é realmente a sua pergunta; sua pergunta é
Certo. Precisamente naqueles casos em que uma das construções de nível superior não atende às suas necessidades.
Meu conselho é que se você se encontrar em uma situação em que as ferramentas de abstração superior existentes não atendam às suas necessidades e deseja implementar uma solução usando threads, você deve identificar a abstração ausente de que realmente precisa e, em seguida, implementar essa abstração usando threads e, em seguida, use a abstração .
fonte
Threads são um bloco de construção básico para certas coisas (nomeadamente paralelismo e assincronia) e, portanto, não devem ser retirados. No entanto , para a maioria das pessoas e a maioria dos casos de uso Há coisas mais apropriadas para uso que você mencionou, como pools de threads (que fornecem uma boa maneira de lidar com muitos pequenos trabalhos em paralelo, sem sobrecarregar a máquina por desova 2000 segmentos de uma vez),
BackgroundWorker
( que encapsula eventos úteis para um único trabalho de curta duração).Mas só porque em muitos casos esses são mais apropriados, pois protegem o programador de reinventar a roda desnecessariamente, cometer erros estúpidos e coisas do tipo, isso não significa que a classe Thread esteja obsoleta. Ele ainda é usado pelas abstrações mencionadas acima e você ainda precisará dele se precisar de controle refinado sobre threads que não são cobertos pelas classes mais especiais.
Na mesma linha,
.NET
não proíbe o uso de arrays, apesar deList<T>
ser mais adequado para muitos casos em que as pessoas usam arrays. Simplesmente porque você ainda pode querer construir coisas que não são cobertas pela biblioteca padrão.fonte
Task
eThread
são abstrações diferentes. Se você deseja modelar um thread, aThread
classe ainda é a escolha mais apropriada. Por exemplo, se você precisa interagir com o tópico atual, não vejo nenhum tipo melhor para isso.No entanto, como você observou, o .NET adicionou várias abstrações dedicadas que são preferíveis
Thread
em muitos casos.fonte
A
Thread
classe não está obsoleta, ainda é útil em circunstâncias especiais.Onde eu trabalho, escrevemos um 'processador de segundo plano' como parte de um sistema de gerenciamento de conteúdo: um serviço do Windows que monitora diretórios, endereços de e-mail e feeds RSS, e toda vez que algo novo aparece, execute uma tarefa nele - normalmente para importar o dados.
As tentativas de usar o pool de threads para isso não funcionaram: ele tenta executar muitas coisas ao mesmo tempo e destruir os discos, então implementamos nosso próprio sistema de pesquisa e execução usando diretamente a
Thread
classe.fonte
As novas opções tornam o uso direto e o gerenciamento dos threads (caros) menos frequentes.
Que é uma maneira muito cara e relativamente complexa de fazer as coisas em paralelo.
Observe que a despesa é o mais importante: você não pode usar um thread completo para fazer um pequeno trabalho, seria contraproducente. O ThreadPool combate os custos, a classe Task as complexidades (exceções, espera e cancelamento).
fonte
Para responder à pergunta " existem casos em que é necessário ou útil usar um objeto Thread antigo simples ", eu diria que um Thread antigo comum é útil (mas não necessário) quando você tem um processo de longa execução que você ganhou ' Nunca interaja com um tópico diferente.
Por exemplo, se você estiver escrevendo um aplicativo que se inscreve para receber mensagens de algum tipo de fila de mensagens e seu aplicativo vai fazer mais do que apenas processar essas mensagens, seria útil usar um Thread porque o thread será independente (ou seja, você não está esperando que isso seja feito) e não é de curta duração. Usar a classe ThreadPool é mais para enfileirar um monte de itens de trabalho de curta duração e permitir que a classe ThreadPool gerencie o processamento eficiente de cada um conforme um novo Thread está disponível. Tarefas podem ser usadas onde você usaria Thread diretamente, mas no cenário acima eu não acho que eles comprariam muito para você. Eles ajudam você a interagir com o tópico mais facilmente (o que o cenário acima não
fonte
System.IO.Threading.Thread
.Provavelmente não é a resposta que você esperava, mas eu uso Thread o tempo todo ao codificar no .NET Micro Framework. MF é bastante reduzido e não inclui abstrações de nível superior e a classe Thread é super flexível quando você precisa obter o último bit de desempenho de uma CPU de baixo MHz.
fonte
Você pode comparar a classe Thread ao ADO.NET. Não é a ferramenta recomendada para realizar o trabalho, mas não está obsoleta. Outras ferramentas são construídas em cima dele para facilitar o trabalho.
Não é errado usar a classe Thread em vez de outras coisas, especialmente se essas coisas não fornecem a funcionalidade de que você precisa.
fonte
Não é definitivamente obsoleto.
O problema com aplicativos multithread é que eles são muito difíceis de acertar (frequentemente comportamento indeterminista, entrada, saída e também o estado interno são importantes), então um programador deve empurrar o máximo de trabalho possível para o framework / ferramentas. Abstraia-o. Mas, o inimigo mortal da abstração é a performance.
Eu escolheria Threads e bloqueios apenas se houvesse sérios problemas de desempenho, metas de alto desempenho.
fonte
Sempre usei a classe Thread quando preciso manter a contagem e o controle sobre os threads que criei. Sei que poderia usar o threadpool para manter todos os meus trabalhos pendentes, mas nunca encontrei uma boa maneira de manter o controle de quanto trabalho está sendo feito ou qual é o seu status.
Em vez disso, crio uma coleção e coloco os threads nelas depois de girá-los - a última coisa que um thread faz é se remover da coleção. Dessa forma, sempre posso dizer quantos threads estão em execução e posso usar a coleção para perguntar a cada um o que está fazendo. Se houver um caso em que eu precise matar todos eles, normalmente você terá que definir algum tipo de sinalizador "Abortar" em seu aplicativo, esperar que cada thread perceba isso por conta própria e se encerrar - no meu caso, eu pode percorrer a coleção e emitir um Thread.Abort para cada um.
Nesse caso, não encontrei uma maneira melhor do que trabalhar diretamente com a classe Thread. Como Eric Lippert mencionou, as outras são apenas abstrações de nível superior e é apropriado trabalhar com as classes de nível inferior quando as implementações de alto nível disponíveis não atendem às suas necessidades. Assim como às vezes você precisa fazer chamadas de API do Win32 quando o .NET não atende às suas necessidades exatas, sempre haverá casos em que a classe Thread é a melhor escolha, apesar dos "avanços" recentes.
fonte