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 do m_hThread elementu członkowskiego danych po zakończeniu wątku. Jeśli jednak używasz tej techniki, ponosisz odpowiedzialność za zniszczenie CWinThread 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