Często widzę, że wspomniano, że Thread.Sleep();
nie należy go używać, ale nie rozumiem, dlaczego tak jest. Jeśli Thread.Sleep();
może powodować problemy, czy są jakieś alternatywne rozwiązania z takim samym skutkiem, które byłyby bezpieczne?
na przykład.
while(true)
{
doSomework();
i++;
Thread.Sleep(5000);
}
inny to:
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
źródło
źródło
goto:
że jest chyba lepsze rozwiązanie twoich problemów niżSleep
.goto
, co bardziej przypomina zapach kodu niż zapach projektu. Nie ma nic złego w tym, że kompilator wstawiagoto
s do twojego kodu: komputer się nie myli. AleThread.Sleep
to nie jest dokładnie to samo; kompilatory nie wstawiają tego wywołania i ma to inne negatywne konsekwencje. Ale tak, ogólne przekonanie, że używanie go jest złe, ponieważ prawie zawsze istnieje lepsze rozwiązanie, jest z pewnością poprawne.sleep()
kod (lub testy), szczeniak umieraOdpowiedzi:
Problemy z wywołaniem
Thread.Sleep
są wyjaśnione dość zwięźle tutaj :Preferowane rozwiązanie: WaitHandles
Najczęściej popełnianym błędem jest użycie
Thread.Sleep
z konstrukcją while ( demo i odpowiedź , fajny wpis na blogu )EDYCJA:
Chciałbym poprawić swoją odpowiedź:
źródło
SCENARIUSZ 1 - oczekiwanie na zakończenie zadania asynchronicznego: Zgadzam się, że WaitHandle / Auto | ManualResetEvent powinno być używane w scenariuszu, w którym wątek oczekuje na zakończenie zadania w innym wątku.
SCENARIUSZ 2 - pętla czasowa while: Jednak jako prymitywny mechanizm czasowy (while + Thread.Sleep) jest całkowicie w porządku dla 99% aplikacji, które NIE wymagają dokładnej wiedzy , kiedy zablokowany wątek powinien się "obudzić *. 200k cykli do utworzenia wątku jest również nieprawidłowe - wątek pętli czasowej i tak musi zostać utworzony, a 200k cykli to kolejna duża liczba (powiedz mi, ile cykli otworzyć wywołania pliku / gniazda / db?).
Więc jeśli while + Thread.Sleep działa, po co komplikować sprawy? Tylko prawnicy składni byliby praktyczni !
źródło
Chciałbym odpowiedzieć na to pytanie z perspektywy polityki kodowania, co może być pomocne lub nie dla nikogo. Ale szczególnie, gdy masz do czynienia z narzędziami przeznaczonymi dla programistów korporacyjnych od 9:00 do 17:00, osoby piszące dokumentację mają tendencję do używania takich słów, jak „nie powinien” i „nigdy” nie znaczy, nie rób tego, chyba że naprawdę wiesz, czego robisz i dlaczego ”.
Kilka innych moich ulubionych w świecie C # to to, że mówią ci, aby „nigdy nie wywoływać blokady (this)” lub „nigdy nie wywoływać GC.Collect ()”. Te dwa są silnie deklarowane na wielu blogach i oficjalnej dokumentacji, a IMO to kompletna dezinformacja. Na pewnym poziomie ta dezinformacja służy swojemu celowi, ponieważ powstrzymuje początkujących od robienia rzeczy, których nie rozumieją, zanim w pełni zbadają alternatywne rozwiązania, ale jednocześnie utrudnia znalezienie PRAWDZIWYCH informacji za pomocą wyszukiwarek, które to wszystko wydają się wskazywać na artykuły, w których mówi się, że nie należy robić czegoś, a nie dają odpowiedzi na pytanie „dlaczego nie?”
Politycznie sprowadza się to do tego, co ludzie uważają za „dobry projekt” lub „zły projekt”. Oficjalna dokumentacja nie powinna dyktować projektu mojej aplikacji. Jeśli naprawdę istnieje techniczny powód, dla którego nie powinieneś wywoływać funkcji sleep (), wówczas dokumentacja IMO powinna zawierać stwierdzenie, że można to wywołać w określonych scenariuszach, ale może zaoferować alternatywne rozwiązania, które są niezależne od scenariusza lub bardziej odpowiednie dla drugiego scenariusze.
Wyraźne wywołanie „sleep ()” jest przydatne w wielu sytuacjach, gdy terminy są jasno określone w kategoriach czasu rzeczywistego, jednak istnieją bardziej wyrafinowane systemy czekania i sygnalizowania wątków, które należy rozważyć i zrozumieć, zanim zaczniesz rzucać w sen ( ) do kodu, a wrzucanie do kodu niepotrzebnych instrukcji sleep () jest ogólnie uważane za taktykę początkujących.
źródło
Jest to 1) .spinning i 2) .polling loop twoich przykładów, przed którymi ludzie ostrzegają , a nie część Thread.Sleep (). Myślę, że Thread.Sleep () jest zwykle dodawany w celu łatwego ulepszenia kodu, który wiruje lub jest w pętli odpytywania, więc jest po prostu powiązany z „złym” kodem.
Ponadto ludzie robią takie rzeczy jak:
gdzie zmienna inWait nie jest dostępna w sposób bezpieczny dla wątków, co również powoduje problemy.
Programiści chcą zobaczyć wątki kontrolowane przez konstrukcje zdarzeń i sygnalizacji i blokowania, a kiedy to zrobisz, nie będziesz potrzebować Thread.Sleep (), a obawy dotyczące dostępu do zmiennych bezpiecznych dla wątków również zostaną wyeliminowane. Na przykład, czy możesz utworzyć procedurę obsługi zdarzeń skojarzoną z klasą FileSystemWatcher i użyć zdarzenia do wyzwolenia drugiego przykładu zamiast zapętlania?
Jak wspomniał Andreas N., przeczytaj artykuł Wątki w C # autorstwa Joe Albahari , jest naprawdę bardzo dobry.
źródło
Thread.Sleep()
inną funkcję i wywołać ją w pętli while?Uśpienie jest używane w przypadkach, gdy niezależne programy, nad którymi nie masz kontroli, mogą czasami korzystać z powszechnie używanego zasobu (na przykład pliku), do którego program musi uzyskać dostęp, gdy działa, i gdy zasób jest przez nie używany inne programy Twój program nie może ich używać. W tym przypadku, gdy uzyskujesz dostęp do zasobu w swoim kodzie, umieszczasz swój dostęp do zasobu w try-catch (aby złapać wyjątek, gdy nie możesz uzyskać dostępu do zasobu) i umieszczasz to w pętli while. Jeśli zasób jest wolny, sen nigdy nie zostanie wywołany. Ale jeśli zasób jest zablokowany, śpisz przez odpowiedni czas i próbujesz ponownie uzyskać dostęp do zasobu (dlatego zapętlasz). Pamiętaj jednak, że musisz umieścić jakiś ogranicznik na pętli, więc nie jest to potencjalnie nieskończona pętla.
źródło
Mam przypadek użycia, którego tutaj nie do końca nie widzę, i będę argumentować, że jest to ważny powód, aby użyć Thread.Sleep ():
W aplikacji konsolowej wykonującej zadania czyszczenia muszę wykonać dużą liczbę dość kosztownych wywołań bazy danych do bazy danych współdzielonej przez tysiące jednoczesnych użytkowników. Aby nie uderzać DB i nie wykluczać innych godzinami, potrzebuję przerwy między połączeniami, rzędu 100 ms. Nie jest to związane z synchronizacją, a jedynie z udzielaniem dostępu do bazy danych innym wątkom.
Poświęcenie 2000-8000 cykli na przełączanie kontekstu między wywołaniami, których wykonanie może zająć 500 ms, jest nieszkodliwe, podobnie jak posiadanie 1 MB stosu na wątek, który działa jako pojedyncza instancja na serwerze.
źródło
Thread.Sleep
w jednowątkowej, jednofunkcyjnej aplikacji konsoli, takiej jak ta, którą opisujesz, jest całkowicie OK.Zgadzam się z wieloma tutaj, ale myślę, że to zależy.
Ostatnio zrobiłem ten kod:
To była prosta funkcja animacji i użyłem
Thread.Sleep
na niej.Mój wniosek, jeśli spełnia swoje zadanie, użyj go.
źródło
Dla tych z Was, którzy nie widzieli jednego ważnego argumentu przeciwko używaniu Thread.Sleep w SCENARIUSZU 2, naprawdę jest jeden - wyjście aplikacji jest wstrzymywane przez pętlę while (SCENARIUSZ 1/3 jest po prostu głupi, więc nie jest wart więcej wspominając)
Wielu, którzy udają, że wiedzą, krzyczą Thread.Sleep is evil nie wymieniło ani jednego ważnego powodu dla tych z nas, którzy domagali się praktycznego powodu, aby go nie używać - ale oto on, dzięki Pete'owi - Thread. jest zły (można go łatwo uniknąć za pomocą timera / handlera)
źródło
Thread.Sleep
nie jest tego powodem (jest to nowy wątek i ciągła pętla while)! możesz po prostu usunąćThread.Sleep
-line - et voila: program również nie wyjdzie ...