Многопоточность: завершение потоков в MFC

Две обычные ситуации вызывают завершение потока: управление функцией завершается или поток не может выполняться до завершения. Если обработчик слов использовал поток для фоновой печати, управляющая функция завершается нормально, если печать выполнена успешно. Если пользователь хочет отменить печать, однако поток фоновой печати должен быть завершен преждевременно. В этом разделе объясняется, как реализовать каждую ситуацию и как получить код выхода потока после его завершения.

Обычное завершение потока

Для рабочего потока обычное завершение потока просто: выйти из управляемой функции и вернуть значение, указывающее причину завершения. Можно использовать функцию AfxEndThread или инструкцию return . Как правило, 0 означает успешное завершение, но это до вас.

Для потока пользовательского интерфейса процесс так же прост: из потока пользовательского интерфейса вызовите PostQuitMessage в пакете SDK для Windows. Единственным параметром, который PostQuitMessage принимает, является код выхода потока. Что касается рабочих потоков, 0 обычно означает успешное завершение.

Преждевременное завершение потока

Завершение потока преждевременно почти так просто: вызов AfxEndThread из потока. Передайте нужный код выхода в качестве единственного параметра. Это останавливает выполнение потока, освобождает стек потока, отсоединяет все библиотеки DLL, подключенные к потоку, и удаляет объект потока из памяти.

AfxEndThread необходимо вызвать из потока, чтобы завершить работу. Если вы хотите завершить поток из другого потока, необходимо настроить метод связи между двумя потоками.

Получение кода выхода потока

Чтобы получить код выхода рабочей роли или потока пользовательского интерфейса, вызовите функцию GetExitCodeThread . Сведения об этой функции см. в пакете SDK для Windows. Эта функция принимает дескриптор потока (хранящегося в m_hThread элементе CWinThread данных объектов) и адрес DWORD.

Если поток по-прежнему активен, GetExitCodeThread помещает STILL_ACTIVE в указанный адрес DWORD; в противном случае код выхода помещается в этот адрес.

Получение кода выхода объектов CWinThread занимает дополнительный шаг. По умолчанию при CWinThread завершении потока объект потока удаляется. Это означает, что невозможно получить доступ к элементу m_hThread данных, так как CWinThread объект больше не существует. Чтобы избежать этой ситуации, выполните одно из следующих действий:

  • Задайте для m_bAutoDelete элемента данных значение FALSE. Это позволяет CWinThread объекту выжить после завершения потока. После завершения потока можно получить доступ к элементу m_hThread данных. Однако если вы используете этот метод, вы несете ответственность за уничтожение CWinThread объекта, так как платформа не будет автоматически удалять ее для вас. Это является предпочтительным методом.

  • Храните дескриптор потока отдельно. После создания потока скопируйте его m_hThread член данных (с помощью ::DuplicateHandle) в другую переменную и получите к ней доступ. Таким образом, объект удаляется автоматически при завершении, и вы по-прежнему можете узнать, почему поток завершился. Будьте осторожны, что поток не завершается, прежде чем можно дублировать дескриптор. Самый безопасный способ сделать это — передать CREATE_SUSPENDED в AfxBeginThread, сохранить дескриптор, а затем возобновить поток путем вызова ResumeThread.

Любой CWinThread метод позволяет определить, почему объект завершился.

См. также

Реализация многопоточности на языке C++ с помощью классов MFC
_endthread, _endthreadex
_beginthread, _beginthreadex
ExitThread