Existem boas regras para quando usar Task.Delay versus Thread.Sleep ?
- Especificamente, existe um valor mínimo para garantir que um seja eficaz / eficiente em relação ao outro?
- Por fim, como o Task.Delay causa a alternância de contexto em uma máquina de estado assíncrona / aguardada, há uma sobrecarga de usá-la?
Respostas:
Use
Thread.Sleep
quando quiser bloquear o encadeamento atual.Use
Task.Delay
quando desejar um atraso lógico sem bloquear o encadeamento atual.A eficiência não deve ser uma preocupação primordial com esses métodos. Seu uso primário no mundo real é como temporizadores de repetição para operações de E / S, que são da ordem de segundos e não de milissegundos.
fonte
Thread.Sleep
irá bloquear o thread atual que causa uma troca de contexto. Se você estiver usando um pool de threads, isso também poderá fazer com que um novo thread seja alocado. As duas operações são bastante pesadas, enquanto as multitarefas cooperativas fornecidas peloTask.Delay
etc são projetadas para evitar toda essa sobrecarga, maximizar a produtividade, permitir o cancelamento e fornecer um código mais limpo.onesi: I would use
Thread.Sleep` para esperar dentro de um método síncrono. No entanto, nunca faço isso no código de produção; na minha experiência, tudo oThread.Sleep
que eu já vi foi indicativo de algum tipo de problema de design que precisa ser corrigido corretamente.A maior diferença entre
Task.Delay
eThread.Sleep
é aTask.Delay
intenção de executar de forma assíncrona. Não faz sentido usarTask.Delay
no código síncrono. É uma péssima idéia usarThread.Sleep
no código assíncrono.Normalmente você ligará
Task.Delay()
com aawait
palavra-chave:ou, se você deseja executar algum código antes do atraso:
Adivinha o que isso vai imprimir? Em execução por 0,0070048 segundos. Se movermos o
await delay
acimaConsole.WriteLine
, em vez disso, ele imprimirá Running por 5.0020168 segundos.Vejamos a diferença com
Thread.Sleep
:Tente prever o que isso imprimirá ...
Além disso, é interessante notar que
Thread.Sleep
é muito mais preciso, a precisão da ms não é realmente um problema, enquantoTask.Delay
pode demorar 15 a 30 ms no mínimo. A sobrecarga em ambas as funções é mínima em comparação com a precisão de ms que elas possuem (useStopwatch
Classe se precisar de algo mais preciso).Thread.Sleep
ainda amarra seu thread,Task.Delay
solte-o para fazer outro trabalho enquanto espera.fonte
Thread.Sleep()
consome um thread inteiro que, de outra forma, poderia ser usado em outro lugar. Se muitas tarefas forem executadas com o Thread.Sleep (), há uma grande chance de esgotar todos os threads do conjunto de threads e prejudicar seriamente o desempenho.async
métodos, pois eles são encorajados a serem usados. Basicamente, é apenas uma má ideia executarThread.Sleep()
em um encadeamento de threads, não uma má ideia em geral. Afinal, háTaskCreationOptions.LongRunning
quando seguir aTask.Factory.StartNew()
rota (embora desanimada) .await wait
Tasl.Delay
usa o timer do sistema. Como "O relógio do sistema" marca "a uma taxa constante.", A velocidade do timer do sistema é de cerca de 16 ms, qualquer atraso solicitado será arredondado para um número de ticks do relógio do sistema, compensado pelo tempo até o primeiro Carraça. Consulte a documentação doTask.Delay
msdn em docs.microsoft.com/en-us/dotnet/api/… e role para baixo para ver os comentários.se o encadeamento atual for eliminado e você o usar
Thread.Sleep
e estiver em execução, poderá obter umThreadAbortException
. ComTask.Delay
você, você sempre pode fornecer um token de cancelamento e matá-lo normalmente. Essa é uma razão que eu escolheriaTask.Delay
. consulte http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspxTambém concordo que a eficiência não é fundamental neste caso.
fonte
await Task.Delay(5000)
. Quando eu mato a tarefa, receboTaskCanceledException
(e a suprimo), mas minha discussão ainda está viva. Arrumado! :)Eu quero adicionar algo. Na verdade,
Task.Delay
é um mecanismo de espera baseado em timer. Se você olhar para a fonte , encontrará uma referência a umaTimer
classe responsável pelo atraso. Por outro lado,Thread.Sleep
na verdade, o encadeamento atual é interrompido, dessa maneira você está apenas bloqueando e desperdiçando um encadeamento. No modelo de programação assíncrona, você sempre deve usarTask.Delay()
se desejar que algo (continuação) aconteça após algum atraso.fonte