2009-06-15 20 views
12

Piszę usługę Windows, która potrzebuje spać przez długi czas (15 godzin to najdłuższy czas, w którym spać, 30 minut jest najkrótsza). Obecnie używam Thread.Sleep (calculTime), aby przełączyć mój kod w tryb uśpienia. Czy Thread.leep jest najlepszą opcją, czy powinienem używać timera? Od jakiegoś czasu googlowałem i nie mogę znaleźć zwięzłej odpowiedzi. Ponieważ jest to usługa Windows, nie muszę się martwić o blokowanie interfejsu użytkownika, więc nie mogę wymyślić powodu, aby nie używać Thread.Sleep.Używanie Thread.Sleep() w usłudze Windows

Każdy wgląd byłby doceniony.

Odpowiedz

19

Użyłbym czasomierza, Thread.Sleep, może spowodować blokowanie, które może uniemożliwić zamknięcie usługi.

Jeśli interwał jest szeroki i regularny, możesz go również zaplanować. Ale jeśli mówisz o długich, niekonsekwentnych odstępach czasu, to tak, Timer będzie lepszy.

7

Powszechnie uważa się za niewłaściwą praktykę stosowanie w wielu przypadkach Thread.Sleep().

Jeśli chcesz, aby usługa działała w tle, użyj zegara.

Jeśli usługa ma być uruchamiana tylko w regularnych odstępach czasu, zalecamy zajrzenie do programu do planowania zadań systemu Windows w celu umożliwienia systemowi Windows uruchomienia aplikacji, gdy jest to potrzebne.

5

Nie należy wstępnie obliczać tak dużych ilości czasu i snu przez wiele godzin. Spocznij w najlepszym razie przez minutę, a potem obudź się i ponownie obliczyć czas, ponownie przespać nie dłużej niż minutę. Zakładam, że obliczenia są bardzo tanie lub mogą być bardzo tanie z buforowaniem. Problem, który próbuję złagodzić, polega na tym, że zegary komputerowe są zaskakująco "skoczne", głównie ze względu na dryf czasu korygowany przez usługę czasu sieciowego, także z powodu oszczędności w świetle dziennym, a także dlatego, że użytkownik dostosowuje zegar. Więc lepiej jest stale przeliczać czas na tak długie interwały, nawet jeśli oznacza to budzenie się co minutę. I nie bądź zaskoczony (tj. Nie twierdz, że), jeśli budzisz się w przeszłości, zegary mogą się cofać w czasie.

1

Inną kwestią, którą należy wziąć pod uwagę, jest to, że wątki są zasobami skończonymi, a każdy wątek zużywa część pamięci (1 MB?) Na swój stos. Mogą również zwiększyć obciążenie harmonogramu.

Teraz, jeśli twoja usługa nie robi wiele więcej, marnowana przestrzeń jest banalna, ale dobrze jest mieć tego świadomość, zanim zaczniesz przydzielać wiele wątków. Używanie ThreadPool i/lub Timerów jest znacznie wydajniejsze.

9

Ponieważ usługa może zostać poproszona o zatrzymanie się w dowolnym momencie przez Menedżera kontroli serwisowej, twój wątek powinien zawsze być gotowy na odpowiedź na te żądania, więc nie powinieneś używać Thread.Sleep(). Zamiast tego utwórz zdarzenie resetowania ręcznego w głównym wątku i użyj jego metody WaitOne z limitem czasu w wątku roboczym. WaitOne zwróci wartość false, gdy upłynie czas.

Po wywołaniu metod OnStop lub OnShutdown klasy serwisowej ustaw zdarzenie, które spowoduje, że WaitOne zwróci wartość true, a następnie możesz opuścić wątek roboczy.