Jak zdobyć oczekiwany Thread.Sleep?

139

Piszę aplikację sieciową opartą na paradygmacie await / sleep.

Czasami zdarzają się błędy połączenia i z mojego doświadczenia wynika, że ​​warto poczekać jakiś czas, a następnie ponowić operację.

Problem polega na tym, że jeśli używam Thread.Sleep lub innej podobnej operacji blokowania w await / async, blokuje całą aktywność w wątku wywołującego.

Czym powinienem zastąpić Thread.Sleep (10000), aby uzyskać taki sam efekt jak

await Thread.SleepAsync(10000)

?

AKTUALIZACJA

Wolę odpowiedź, która robi to bez tworzenia dodatkowego wątku

Arsen Zahray
źródło

Odpowiedzi:

323

Inne odpowiedzi sugerujące rozpoczęcie nowego wątku to zły pomysł - nie ma takiej potrzeby. Częścią celu async/ awaitjest zmniejszenie liczby wątków potrzebnych aplikacji.

Zamiast tego powinieneś użyć, Task.Delayktóry nie wymaga nowego wątku i został zaprojektowany właśnie do tego celu:

// Execution of the async method will continue one second later, but without
// blocking.
await Task.Delay(1000);
Jon Skeet
źródło
Nadal mam do czynienia z rzeczami a4.5. Gdzie jest gałąź wykonania w kodzie po tej instrukcji? Czy część nie-uśpiona / blokująca wykonuje ją, czy „wątek”, który czeka? Czy główne nieblokujące wykonanie po prostu opuszcza następujący po nim blok (czyli powrót)?
kenny
1
Tak. To DOKŁADNIE to, czego potrzebuję
Arsen Zahray
1
@kenny: Moje asyncintro może być pomocne. Gdy awaitable zwrócone przez Task.Delayjest awaited, ponieważ nie jest ukończone, bieżąca metoda zwraca niekompletne zadanie. Później, gdy Delayzakończy się (poza licznikiem czasu, a nie wątkiem), reszta metody zostanie zaplanowana do uruchomienia. Kontynuacja przebiega w „kontekście”, który może powrócić do tego samego oryginalnego wątku - szczegóły na moim blogu.
Stephen Cleary
@StephenCleary dzięki za to. Więc mam rację mówiąc, że kod po await jest „zaplanowany” do wykonania, a wątek wywołujący powraca?
kenny
2
Tak, wątek wywołujący zwraca (natychmiast) i kod po awaitzaplanowaniu (ostatecznie).
Stephen Cleary