Wszyscy znamy doskonale funkcję Sleep
, która w Windows API służy do zawieszania działania wątku na określony czas (podawany w milisekundach). Wydawałoby się, że musi to być najprostsza funkcja z tego API, jaką tylko można sobie wyobrazić – bo co może być skomplikowanego w “zwykłej pauzie”? A okazuje się, że jak najbardziej może :)
Używając Sleep
– zwłaszcza w swej zwykłej wersji – musimy bowiem pamiętać przynajmniej o dwóch sprawach:
Sleep(INFINITE);
sprawi, że właściwie możemy ów wątek wyrzucić do kosza, gdyż nie da się już go odwiesić (funkcja ResumeThread
wywołana z innego wątku nic tu nie pomoże).MsgWaitForMultipleObjectsEx
albo po prostu GetTickCount
wraz z wewnętrzną pętlą komunikatów).Ex
funkcji Sleep
. Różni się on od oryginału tym, że rozpoczęte przez niego oczekiwanie można przerwać, jeśli sobie tego zażyczymy. Wątek uśpiony przez SleepEx
może być przedwcześnie obudzony, gdy otrzyma informacje o zakończeniu asynchronicznej operacji I/O lub asynchronicznego wywołania procedury (APC).Sleep
. Jest on bowiem determinowany przez długość tzw. kwantów czasu (time slices), jakie system operacyjny przydziela kolejnym wątkom, by zapewnić złudzenie ich jednoczesnego wykonania. Działanie Sleep
polega w rzeczywistości na oddaniu systemowi reszty kwantu czasu, który został przydzielony wątkowi; przestawienie wątku w stan “nieuruchamialności” na podaną ilość milisekund; a następnie na wznowieniu jego pracy, gdy ponownie otrzyma czas procesora od systemowego schedulera. W sumie więc czas uśpienia będzie równy:PozostałyKwantCzasu + ParametrSleep + CzasDoUaktywnieniaWątku
Stąd wynikają dwa wnioski. Po pierwsze, nie powinniśmy nigdy używać Sleep
jako sposobu na mierzenie czasu – już poczciwy GetTickCount
sprawi się tu znacznie lepiej. Po drugie, wywołanie Sleep(0);
jest jak najbardziej dopuszczalne i oznacza przedwczesne zrzeczenie się kwantu czasu, jaki wątek dostał od systemu. W czasach 16-bitowych wersji Windows i wielowątkowości bez wywłaszczała była od tego specjalna funkcja Yield
, którą należało często wywoływać, aby przełączanie wątków w ogóle było możliwe. Teraz rzecz jasna nie jest to konieczne, ale nadal może być przydatne dla zasygnalizowania, że nasz wątek nie robi nic pożytecznego, a tylko w brzydki sposób na coś czeka (tzw. busy waiting).
O tych dwóch szczegółach odnośnie funkcji Sleep
dobrze jest pamiętać, jeśli nasze wątki chcemy usypiać. Jako programiści Windows możemy się aczkolwiek podbudować tym, że nie mamy przy tym takich problemów jak koderzy piszący pod Linuksem. Tam sleep
może być potencjalnie zaimplementowany na sygnałach, co wymaga ostrożności przy stosowaniu go razem z funkcjami alarm
i signal
.
Adding comments is disabled.
Comments are disabled.