Wielowątkowość: kończenie wątków w MFC
Dwie normalne sytuacje powodują zakończenie wątku: funkcja sterująca kończy działanie lub wątek nie może zostać uruchomiony do ukończenia. Jeśli procesor tekstów używa wątku do drukowania w tle, funkcja kontrolująca zakończy się normalnie, jeśli drukowanie zakończy się pomyślnie. Jeśli jednak użytkownik chce anulować drukowanie, przedwcześnie należy przerwać drukowanie w tle. W tym temacie wyjaśniono, jak zaimplementować każdą sytuację i jak uzyskać kod zakończenia wątku po jego zakończeniu.
Normalne kończenie wątku
W przypadku wątku roboczego normalne zakończenie wątku jest proste: Zamknij funkcję kontrolującą i zwróć wartość, która oznacza przyczynę zakończenia. Możesz użyć funkcji AfxEndThread lub instrukcji return
. Zazwyczaj 0 oznacza pomyślne zakończenie, ale to do Ciebie.
W wątku interfejsu użytkownika proces jest tak prosty: z poziomu wątku interfejsu użytkownika wywołaj metodę PostQuitMessage w zestawie WINDOWS SDK. Jedynym parametrem, który PostQuitMessage
przyjmuje, jest kod zakończenia wątku. Jeśli chodzi o wątki robocze, 0 zwykle oznacza pomyślne ukończenie.
Przedwczesne zakończenie wątku
Przedwczesne zakończenie wątku jest niemal tak proste: wywołaj element AfxEndThread z poziomu wątku. Przekaż żądany kod zakończenia jako jedyny parametr. Spowoduje to zatrzymanie wykonywania wątku, cofnięcie przydziału stosu wątku, odłączenie wszystkich bibliotek DLL dołączonych do wątku i usunięcie obiektu wątku z pamięci.
AfxEndThread
musi być wywoływana z wewnątrz wątku, aby zakończyć. Jeśli chcesz przerwać wątek z innego wątku, musisz skonfigurować metodę komunikacji między dwoma wątkami.
Pobieranie kodu zakończenia wątku
Aby uzyskać kod zakończenia procesu roboczego lub wątku interfejsu użytkownika, wywołaj funkcję GetExitCodeThread . Aby uzyskać informacje o tej funkcji, zobacz zestaw Windows SDK. Ta funkcja pobiera uchwyt do wątku (przechowywanego m_hThread
w elemencie danych obiektów CWinThread
) i adres DWORD.
Jeśli wątek jest nadal aktywny, GetExitCodeThread
umieszcza STILL_ACTIVE w podanym adresie DWORD; w przeciwnym razie kod zakończenia jest umieszczany w tym adresie.
Pobieranie kodu zakończenia obiektów CWinThread wymaga dodatkowego kroku. Domyślnie po zakończeniu wątku CWinThread
obiekt wątku jest usuwany. Oznacza to, że nie można uzyskać dostępu do m_hThread
elementu członkowskiego danych, ponieważ CWinThread
obiekt już nie istnieje. Aby uniknąć tej sytuacji, wykonaj jedną z następujących czynności:
Ustaw element członkowski
m_bAutoDelete
danych na WARTOŚĆ FALSE.CWinThread
Dzięki temu obiekt może przetrwać po zakończeniu wątku. Następnie możesz uzyskać dostęp dom_hThread
elementu członkowskiego danych po zakończeniu wątku. Jeśli jednak używasz tej techniki, ponosisz odpowiedzialność za zniszczenieCWinThread
obiektu, ponieważ struktura nie usunie go automatycznie. Jest to preferowana metoda.Przechowuj uchwyt wątku oddzielnie. Po utworzeniu wątku skopiuj element
m_hThread
członkowski danych (przy użyciu::DuplicateHandle
) do innej zmiennej i uzyskaj do niej dostęp za pośrednictwem tej zmiennej. W ten sposób obiekt jest usuwany automatycznie po zakończeniu i nadal można dowiedzieć się, dlaczego wątek został przerwany. Należy zachować ostrożność, że wątek nie kończy się przed zduplikowanie uchwytu. Najbezpieczniejszym sposobem wykonania tej czynności jest przekazanie CREATE_SUSPENDED do elementu AfxBeginThread, zapisanie uchwytu, a następnie wznowienie wątku przez wywołanie elementu ResumeThread.
Każda z metod pozwala określić, dlaczego CWinThread
obiekt został zakończony.
Zobacz też
Wielowątkowość z C++ i MFC
_endthread, _endthreadex
_beginthread, _beginthreadex
ExitThread