Multithreading: Finalizar subprocesos en MFC
Hay dos situaciones normales que ocasionan que un subproceso finalice: la función de control se sale o el subproceso no puede ejecutarse hasta su finalización. Si un procesador de texto usa un subproceso para la impresión en segundo plano, la función de control finalizará normalmente si la impresión se completa correctamente. Sin embargo, si el usuario desea cancelar la impresión, el subproceso de impresión en segundo plano debe finalizar prematuramente. En este tema se explica cómo implementar cada situación y cómo obtener el código de salida de un subproceso una vez finalizado.
Finalización normal del subproceso
Para un subproceso de trabajo, la finalización normal del subproceso es sencilla: salga de la función de control y devuelva un valor que indique el motivo de la finalización. Puede usar la función AfxEndThread o una instrucción return
. Normalmente, 0 significa una finalización correcta, pero usted debe decidir ello.
Para un subproceso de interfaz de usuario, el proceso es igual de sencillo: desde el subproceso de interfaz de usuario, llame a PostQuitMessage en Windows SDK. El único parámetro que PostQuitMessage
toma es el código de salida del subproceso. En cuanto a los subprocesos de trabajo, 0 suele significar la finalización correcta.
Finalización prematura de un subproceso
Finalizar un subproceso prematuramente es casi tan sencillo: llame a AfxEndThread desde el subproceso. Pase el código de salida deseado como único parámetro. Esto detiene la ejecución del subproceso, desasigna la pila del subproceso, desasocia todas las DLL asociadas al subproceso y elimina el objeto del subproceso de la memoria.
Se debe llamar a AfxEndThread
desde el subproceso que se finalizará. Si desea finalizar un subproceso de otro subproceso, debe configurar un método de comunicación entre los dos subprocesos.
Recuperar el código de salida de un subproceso
Para obtener el código de salida del subproceso de trabajo o del subproceso de interfaz de usuario, llame a la función GetExitCodeThread. Para información sobre esta función, consulte Windows SDK. Esta función toma el manipulador del subproceso (almacenado en el miembro de datos m_hThread
de los objetos CWinThread
) y la dirección de un DWORD.
Si el subproceso sigue activo, GetExitCodeThread
coloca STILL_ACTIVE en la dirección DWORD proporcionada; de lo contrario, el código de salida se coloca en esta dirección.
La recuperación del código de salida de los objetos CWinThread toma un paso adicional. De forma predeterminada, cuando finaliza un subproceso CWinThread
, se elimina el objeto de subproceso. Esto significa que no se puede acceder al miembro de datos m_hThread
porque el objeto CWinThread
ya no existe. Para evitar esta situación, realice una de las acciones siguientes:
Establezca el miembro de datos
m_bAutoDelete
en FALSE. Esto permite que el objetoCWinThread
sobreviva una vez finalizado el subproceso. Puede acceder al miembro de datosm_hThread
después de finalizado el subproceso. Sin embargo, si usa esta técnica, es responsable de destruir el objetoCWinThread
porque el marco no lo eliminará automáticamente por usted. Este es el método preferido.Almacene el manipulador del subproceso por separado. Una vez creado el subproceso, copie su miembro de datos
m_hThread
(mediante::DuplicateHandle
) en otra variable y acceda a ella a través de esa variable. De este modo, el objeto se elimina automáticamente cuando se produce la finalización y todavía puede averiguar por qué finalizó el subproceso. Tenga cuidado de que el subproceso no finalice antes de que pueda duplicar el manipulador. La manera más segura de hacerlo es pasar CREATE_SUSPENDED a AfxBeginThread, almacenar el manipulador y, a continuación, reanudar el subproceso mediante una llamada a ResumeThread.
Cualquiera de los métodos permite determinar por qué un objeto CWinThread
finalizó.
Consulte también
Multithreading con C++ y MFC
_endthread, _endthreadex
_beginthread, _beginthreadex
ExitThread