Udostępnij za pośrednictwem


Funkcje oczekiwania

funkcje Wait zezwalają wątkowi na blokowanie własnego wykonywania. Funkcje oczekiwania nie są zwracane, dopóki określone kryteria nie zostaną spełnione. Typ funkcji oczekiwania określa zestaw używanych kryteriów. Po wywołaniu funkcji wait sprawdza, czy kryteria oczekiwania zostały spełnione. Jeśli kryteria nie zostały spełnione, wątek wywołujący wprowadza stan oczekiwania do momentu spełnienia warunków kryteriów oczekiwania lub upływu określonego interwału limitu czasu.

Funkcje oczekiwania pojedynczego obiektu

Funkcje SignalObjectAndWait, WaitForSingleObjecti WaitForSingleObjectEx wymagają dojścia do jednego obiektu synchronizacji. Te funkcje są zwracane, gdy wystąpi jeden z następujących elementów:

  • Określony obiekt jest w stanie sygnału.
  • Interwał limitu czasu upłynie. Interwał limitu czasu można ustawić na wartość nieskończoną, aby określić, że oczekiwanie nie zostanie przekroczone.

Funkcja SignalObjectAndWait umożliwia niepodzielne ustawienie stanu obiektu na sygnalizowany i oczekiwanie na ustawienie stanu innego obiektu na sygnał.

Funkcje oczekiwania na wiele obiektów

WaitForMultipleObjects, WaitForMultipleObjectsEx, MsgWaitForMultipleObjectsi MsgWaitForMultipleObjectsEx funkcje wywołujące umożliwiają określenie tablicy zawierającej co najmniej jeden uchwyt obiektu synchronizacji. Te funkcje są zwracane, gdy wystąpi jeden z następujących elementów:

  • Stan każdego z określonych obiektów jest ustawiony na sygnał lub stany wszystkich obiektów zostały ustawione na sygnał. Określasz, czy jeden lub wszystkie stany będą używane w wywołaniu funkcji.
  • Interwał limitu czasu upłynie. Interwał limitu czasu można ustawić na wartość nieskończoną, aby określić, że oczekiwanie nie zostanie przekroczone.

Funkcja MsgWaitForMultipleObjects i MsgWaitForMultipleObjectsEx umożliwia określanie obiektów zdarzeń wejściowych w tablicy obsługi obiektów. Odbywa się to po określeniu typu danych wejściowych do oczekiwania w kolejce wejściowej wątku. Na przykład wątek może użyć MsgWaitForMultipleObjects, aby zablokować jego wykonywanie, dopóki stan określonego obiektu nie zostanie ustawiony na sygnalizowanie i w kolejce wejściowej wątku są dostępne dane wejściowe myszy. Wątek może używać funkcji GetMessage lub PeekMessageA lub PeekMessageW, aby pobrać dane wejściowe.

Podczas oczekiwania na ustawienie stanów wszystkich obiektów na sygnalizator, te funkcje wielokrotnego obiektu nie modyfikują stanów określonych obiektów do momentu ustawienia stanów wszystkich obiektów. Na przykład stan obiektu mutex można zasygnalizować, ale wątek wywołujący nie uzyskuje własności, dopóki stany innych obiektów określonych w tablicy również nie zostaną ustawione na sygnał. W międzyczasie inny wątek może uzyskać własność obiektu mutex, ustawiając jego stan na niepodpisany.

Podczas oczekiwania na ustawienie stanu pojedynczego obiektu na zasygnalizowany te funkcje wielokrotnego obiektu sprawdzają uchwyty w tablicy w kolejności rozpoczynającej się od indeksu 0, dopóki jeden z obiektów nie zostanie zasygnalizowany. Jeśli zasygnalizowano wiele obiektów, funkcja zwraca indeks pierwszego uchwytu w tablicy, którego obiekt został zasygnalizowany.

Funkcje oczekiwania z możliwością alertów

MsgWaitForMultipleObjectsEx, SignalObjectAndWait, WaitForMultipleObjectsExi WaitForSingleObjectEx funkcji oczekiwania, w których mogą opcjonalnie wykonać operację oczekiwania z możliwością alertu. W operacji oczekiwania z możliwością alertu funkcja może zwracać dane po spełnieniu określonych warunków, ale może również zwrócić, jeśli system kolejkuje procedurę uzupełniania we/wy lub APC do wykonania przez wątek oczekiwania. Aby uzyskać więcej informacji na temat operacji oczekiwania z możliwością alertów i procedur uzupełniania we/wy, zobacz Synchronizacja i nakładające się dane wejściowe i wyjściowe. Aby uzyskać więcej informacji na temat interfejsów API, zobacz Asynchroniczne wywołania procedur.

Zarejestrowane funkcje oczekiwania

Funkcja RegisterWaitForSingleObject różni się od innych funkcji oczekiwania w tym, że operacja oczekiwania jest wykonywana przez wątek z puli wątków . Po spełnieniu określonych warunków funkcja wywołania zwrotnego jest wykonywana przez wątek procesu roboczego z puli wątków.

Domyślnie zarejestrowana operacja oczekiwania jest operacją oczekiwania wielokrotnego. System resetuje czasomierz za każdym razem, gdy zdarzenie jest sygnalizowane (lub interwał limitu czasu upłynie), dopóki nie wywołasz funkcji UnregisterWaitEx, aby anulować operację. Aby określić, że operacja oczekiwania powinna być wykonywana tylko raz, ustaw parametr dwFlagsRegisterWaitForSingleObject na wartość WT_EXECUTEONLYONCE.

Jeśli wątek wywołuje funkcje korzystające z interfejsów API, ustaw parametr dwFlagsRegisterWaitForSingleObject na WT_EXECUTEINPERSISTENTTHREAD.

Oczekiwanie na adres

Wątek może użyć funkcji WaitOnAddress czekać, aż wartość adresu docelowego zmieni się z niektórych niepożądanych wartości na dowolną inną wartość. Dzięki temu wątki mogą czekać na zmianę wartości bez konieczności uruchamiania lub obsługi problemów z synchronizacją, które mogą wystąpić, gdy wątek przechwytuje niepożądane wartości, ale wartość zmienia się, zanim wątek będzie mógł czekać.

WaitOnAddress zwraca wartość, gdy kod modyfikujący wartość docelową sygnalizuje zmianę przez wywołanie WakeByAddressSingle w celu wznowienia pojedynczego wątku oczekiwania lub WakeByAddressAll w celu wznowienia wszystkich oczekujących wątków. Jeśli zostanie określony interwał limitu czasu z WaitOnAddress i żaden wątek nie wywołuje funkcji wznawiania, funkcja zwraca czas upływu interwału. Jeśli nie określono interwału limitu czasu, wątek czeka na czas nieokreślony.

Funkcje oczekiwania i interwały limitu czasu

Dokładność określonego interwału limitu czasu zależy od rozdzielczości zegara systemowego. Zegar systemowy "kleszcze" w stałym tempie. Jeśli interwał limitu czasu jest mniejszy niż rozdzielczość zegara systemowego, czas oczekiwania może przekraczać limit czasu krótszy niż określony czas. Jeśli interwał limitu czasu jest większy niż jeden znacznik, ale mniej niż dwa, oczekiwanie może być w dowolnym miejscu między jednym i dwoma kleszczami itd.

Aby zwiększyć dokładność interwału limitu czasu dla funkcji oczekiwania, wywołaj funkcję timeGetDevCaps, aby określić obsługiwaną minimalną rozdzielczość czasomierza oraz funkcję timeBeginPeriod, aby ustawić rozdzielczość czasomierza na wartość minimalną. Należy zachować ostrożność podczas wywoływania timeBeginPeriod, ponieważ częste wywołania mogą znacząco wpływać na zegar systemowy, użycie energii systemowej i harmonogram. Jeśli wywołasz timeBeginPeriod, wywołaj ją raz na początku aplikacji i pamiętaj, aby wywołać funkcję timeEndPeriod na samym końcu aplikacji.

Funkcje oczekiwania i obiekty synchronizacji

Funkcje oczekiwania mogą modyfikować stany niektórych typów obiektów synchronizacji . Modyfikacja występuje tylko dla obiektu lub obiektów, których stan sygnalizowany spowodował zwrócenie funkcji. Funkcje oczekiwania mogą modyfikować stany obiektów synchronizacji w następujący sposób:

  • Liczba obiektu semafora zmniejsza się o jeden, a stan semafora jest ustawiony na niepodpisany, jeśli jego liczba wynosi zero.
  • Stany mutex, zdarzenia automatycznego resetowania i obiekty powiadomień o zmianie są ustawione na niepodpisane.
  • Stan czasomierza synchronizacji jest ustawiony na niepodpisany.
  • Stany zdarzenia ręcznego resetowania, czasomierza resetowania ręcznego, procesu, wątku i obiektów wejściowych konsoli nie mają wpływu na funkcję oczekiwania.

Oczekiwanie na funkcje i tworzenie systemu Windows

Należy zachować ostrożność podczas korzystania z funkcji oczekiwania i kodu, który bezpośrednio lub pośrednio tworzy okna. Jeśli wątek tworzy jakiekolwiek okna, musi przetwarzać komunikaty. Emisje komunikatów są wysyłane do wszystkich okien w systemie. Jeśli masz wątek, który używa funkcji oczekiwania bez interwału przekroczenia limitu czasu, system będzie zakleszać. Dwa przykłady kodu, który pośrednio tworzy okna, to DDE i funkcja CoInitialize. W związku z tym, jeśli masz wątek, który tworzy okna, użyj MsgWaitForMultipleObjects lub MsgWaitForMultipleObjectsEx, a nie innych funkcji oczekiwania.