Costumo ver mencionado que Thread.Sleep();
não deve ser usado, mas não consigo entender por que isso acontece. Se Thread.Sleep();
puder causar problemas, existem soluções alternativas com o mesmo resultado que seriam seguras?
por exemplo.
while(true)
{
doSomework();
i++;
Thread.Sleep(5000);
}
outro é:
while (true)
{
string[] images = Directory.GetFiles(@"C:\Dir", "*.png");
foreach (string image in images)
{
this.Invoke(() => this.Enabled = true);
pictureBox1.Image = new Bitmap(image);
Thread.Sleep(1000);
}
}
c#
multithreading
sleep
Burimi
fonte
fonte
goto:
ou seja, provavelmente existe uma solução melhor para seus problemas do queSleep
.goto
, que é mais um cheiro de código do que um cheiro de design. Não há nada errado com um compilador inserindogoto
s no seu código: o computador não fica confuso. MasThread.Sleep
não é exatamente o mesmo; compiladores não inserem essa chamada e isso tem outras consequências negativas. Mas sim, o sentimento geral de que usá-lo está errado, porque quase sempre existe uma solução melhor, certamente está correta.sleep()
em código (ou testes) um filhote de cachorro morreRespostas:
Os problemas com a chamada
Thread.Sleep
são explicados de maneira bastante sucinta aqui :A solução preferida: WaitHandles
O erro mais cometido é usar
Thread.Sleep
com uma construção while ( demonstração e resposta , boa entrada de blog )EDIT:
Gostaria de melhorar minha resposta:
fonte
CENÁRIO 1 - aguarde a conclusão da tarefa assíncrona: concordo que WaitHandle / Auto | ManualResetEvent deve ser usado no cenário em que um thread aguarda a conclusão da tarefa em outro thread.
CENÁRIO 2 - temporização enquanto loop: No entanto, como um mecanismo de temporização bruto (while + Thread.Sleep) é perfeitamente adequado para 99% dos aplicativos que NÃO requerem saber exatamente quando o Thread bloqueado deve "acordar *. O argumento necessário" Os ciclos de 200k para criar o encadeamento também são inválidos - o encadeamento do loop de sincronização precisa ser criado de qualquer maneira e os ciclos de 200k são apenas outro grande número (diga-me quantos ciclos para abrir uma chamada de arquivo / soquete / db?).
Então, se enquanto o + Thread.Sleep funciona, por que complicar as coisas? Somente advogados de sintaxe seriam práticos !
fonte
Gostaria de responder a essa pergunta de uma perspectiva da política de codificação, que pode ou não ser útil a alguém. Mas, particularmente quando você lida com ferramentas destinadas a programadores corporativos de 9 a 5, as pessoas que escrevem documentação tendem a usar palavras como "não deveriam" e "nunca" querem dizer "não fazem isso a menos que você realmente saiba o que quer." estamos fazendo e por que ".
Alguns dos meus outros favoritos no mundo C # são que eles dizem para você "nunca chamar lock (this)" ou "nunca chamar GC.Collect ()". Esses dois são declarados à força em muitos blogs e documentação oficial, e a IMO é desinformação completa. Em certo nível, essa desinformação serve a seu propósito, pois impede os iniciantes de fazer coisas que não entendem antes de pesquisar completamente as alternativas, mas, ao mesmo tempo, dificulta a obtenção de informações reais através de mecanismos de pesquisa que todos parecem apontar para artigos dizendo para você não fazer algo enquanto não oferece resposta à pergunta "por que não?"
Politicamente, tudo se resume ao que as pessoas consideram "bom design" ou "mau design". A documentação oficial não deve ditar o design do meu aplicativo. Se houver realmente uma razão técnica para você não chamar sleep (), a IMO deve informar a documentação de que é totalmente aceitável chamá-la em cenários específicos, mas talvez ofereça algumas soluções alternativas que sejam independentes de cenário ou mais apropriadas para o outro cenários.
Chamar claramente "sleep ()" é útil em muitas situações em que os prazos são claramente definidos em termos de tempo real, no entanto, existem sistemas mais sofisticados para aguardar e sinalizar threads que devem ser considerados e entendidos antes de você começar a dormir ( ) em seu código, e jogar instruções sleep () desnecessárias em seu código é geralmente considerada uma tática para iniciantes.
fonte
É o loop 1) .spinning e 2) .polling dos seus exemplos que as pessoas advertem , não a parte Thread.Sleep (). Eu acho que Thread.Sleep () geralmente é adicionado para melhorar facilmente o código que está girando ou em um loop de pesquisa, por isso está associado apenas ao código "ruim".
Além disso, as pessoas fazem coisas como:
onde a variável inWait não é acessada de maneira segura para threads, o que também causa problemas.
O que os programadores desejam ver são os threads controlados pelas construções Events, Signaling and Locking e, quando você faz isso, não precisa de Thread.Sleep (), e as preocupações com o acesso variável seguro por thread também são eliminadas. Como exemplo, você pode criar um manipulador de eventos associado à classe FileSystemWatcher e usar um evento para acionar seu segundo exemplo em vez de fazer um loop?
Como Andreas N. mencionou, leia Threading in C #, de Joe Albahari , é realmente muito bom.
fonte
Thread.Sleep()
com outra função e chamar isso no loop while?A suspensão é usada nos casos em que programas independentes sobre os quais você não tem controle podem às vezes usar um recurso comumente usado (por exemplo, um arquivo), que seu programa precisa acessar quando é executado e quando o recurso está em uso por esses outros programas que seu programa está impedido de usá-lo. Nesse caso, em que você acessa o recurso no seu código, coloca o acesso ao recurso em uma tentativa de captura (para capturar a exceção quando não é possível acessar o recurso) e o coloca em um loop while. Se o recurso estiver livre, o sono nunca será chamado. Mas se o recurso estiver bloqueado, você dorme por um período de tempo apropriado e tenta acessar o recurso novamente (é por isso que está fazendo um loop). No entanto, lembre-se de que você deve colocar algum tipo de limitador no loop, para que não seja um loop potencialmente infinito.
fonte
Eu tenho um caso de uso que ainda não vejo abordado aqui e argumentarei que esse é um motivo válido para usar Thread.Sleep ():
Em um aplicativo de console executando tarefas de limpeza, preciso fazer uma grande quantidade de chamadas de banco de dados bastante caras para um banco de dados compartilhado por milhares de usuários simultâneos. Para não martelar o banco de dados e excluir outros por horas, precisarei de uma pausa entre as chamadas, na ordem de 100 ms. Isso não está relacionado ao tempo, apenas para fornecer acesso ao banco de dados para outros threads.
Gastar 2000-8000 ciclos na alternância de contexto entre chamadas que podem levar 500 ms para executar é benigno, assim como ter 1 MB de pilha para o encadeamento, que é executado como uma única instância em um servidor.
fonte
Thread.Sleep
em um aplicativo de console de thread único e de propósito único como o que você descreve está perfeitamente bem.Eu concordo com muitos aqui, mas também acho que depende.
Recentemente eu fiz este código:
Era uma função animada simples, e eu a usei
Thread.Sleep
.Minha conclusão, se funcionar, use-o.
fonte
Para aqueles que não viram um argumento válido contra o uso do Thread.Sleep no SCENARIO 2, existe realmente um - a saída do aplicativo é mantida pelo loop while (o SCENARIO 1/3 é simplesmente estúpido, portanto não merece mais mencionando)
Muitos que fingem estar gritando Thread.Sleep é malvado, não mencionou uma única razão válida para aqueles de nós que exigiram uma razão prática para não usá-lo - mas aqui está, graças a Pete - Thread.Sleep é mau (pode ser facilmente evitado com um temporizador / manipulador)
fonte
Thread.Sleep
não é a razão para isso (o novo thread e o contínuo while-loop)! você pode simplesmente remover oThread.Sleep
-line - et voila: o programa não sairá bem ...