Substituição Thread.Sleep no .NET para Windows Store

98

Thread.Sleep não parece ser compatível com .NET para aplicativos da Windows Store.

Por exemplo, este

System.Threading.Thread.Sleep(1000);

irá compilar ao direcionar qualquer .NET Framework (2.0, 3.5, 4.0, 4.5), mas não ao direcionar o .NET para aplicativos da Windows Store (ou em uma biblioteca de classes portátil que direciona 4.5 e store).

System.Threading.Thread ainda está lá, mas não tem o método Sleep.

Eu preciso atrasar algo por alguns segundos no meu aplicativo, há um substituto adequado?

EDITAR por que o atraso é necessário: Meu aplicativo é um jogo e o atraso é para fazer parecer que o oponente do computador está "pensando" em seu próximo movimento. O método já é chamado de forma assíncrona (thread principal não está bloqueado), eu só quero diminuir o tempo de resposta.

Max
fonte
2
Considerando que os aplicativos da Windows Store não devem ser capazes de congelar a IU (tudo deve ser assíncrono), faz sentido que isso não seja compatível.
Sruly
2
Você tem eventos ou a Monitoraula? Você pode usar o Waitmétodo com um tempo limite para simular um sono.
Tudor
isso é para Apptivate.ms? : 3
EaterOfCode
3
Yay por banir Thread.Sleeppara a lata de lixo de tecnologia ruim.
spender

Respostas:

203

Os aplicativos da Windows Store adotam a assincronia - e uma "pausa assíncrona" é fornecida por Task.Delay. Portanto, em um método assíncrono, você escreveria:

await Task.Delay(TimeSpan.FromSeconds(30));

... ou qualquer atraso que você quiser. O método assíncrono continuará 30 segundos depois, mas o thread não será bloqueado, assim como para todas as awaitexpressões.

Jon Skeet
fonte
1
Infelizmente, Task.Delay não parece ser suportado ao direcionar o .NET 4.5 + store + WP7 em uma biblioteca de classes portátil .. Acho que terei que mover isso para as classes específicas da plataforma.
Máx.
1
@Max: Não, porque não existia antes do .NET 4.5. IIRC, WP7 em si não tem nenhum suporte TPL. (Posso estar errado ...)
Jon Skeet
4
Você pode aderir, .RunSynchronously()se necessário.
HappyNomad
1
@RAM: Bem, Thread.Sleep é compatível com .NET 3.5, então a pergunta não se aplica. Sem dúvida você tem uma pergunta, mas não parece a mesma que esta aqui. Leia tinyurl.com/stack-hints e faça uma nova pergunta.
Jon Skeet
2
@RAM: Não tenho certeza de como deveria adivinhar isso pelos seus comentários. Já existem muitas perguntas semelhantes no SO sobre WPF e animação.
Jon Skeet de
46

Odeio dizer o óbvio, mas no caso de alguém querer uma única linha System.Threading.Tasks.Task.Delay(3000).Wait()

Antony Thomas
fonte
20

Eu simplesmente tive o mesmo problema e encontrei outra solução interessante que gostaria de compartilhar com vocês. Se você realmente quiser bloquear o tópico, eu faria assim (obrigado @Brannon pela dica "slim"):

// `waitHandle.Set` is never called, so we wait always until the timeout occurs
using (var waitHandle = new ManualResetEventSlim(initialState: false))
{
    waitHandle.Wait(TimeSpan.FromSeconds(5));
}
Johannes Egger
fonte
Esta é a melhor resposta para codificação portátil.
zezba9000
Use a versão "fina" disso.
Brannon
11

MainPage.xaml.cs

public MainPage()
{
  this.InitializeComponent();
  this.WaitForFiveSeconds();
}

private async void WaitForFiveSeconds()
{
  await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(5));
  // do something after 5 seconds!
}
Benny Neugebauer
fonte
-7

Quase NENHUMA razão (exceto para fins de teste) SEMPRE usar Thread.Sleep().

SE (e somente se) você tiver um bom motivo para enviar um thread para dormir, você pode querer verificar Task.Delay(), que você pode aguardar para "esperar" por um tempo especificado. Embora nunca seja uma boa ideia ter um fio parado e não fazer nada. Prática ruim ...

igrimpe
fonte
9
Discordo. Se o encadeamento for um encadeamento em segundo plano e a suspensão for curta, é mais eficiente mantê-lo suspenso por alguns milissegundos do que usar um cronômetro.
Jason Steele
1
e às vezes você diz para fazer isso apesar de aconselhar a referida figura de autoridade sobre as consequências;)
Jordan