Multithreading: crear subprocesos de trabajo en MFCMultithreading: Creating Worker Threads in MFC

Un subproceso de trabajo se usa normalmente para controlar las tareas en segundo plano que el usuario no debería tener que esperar para continuar usando la aplicación.A worker thread is commonly used to handle background tasks that the user should not have to wait for to continue using your application. Tareas como el recálculo y la impresión en segundo plano son buenos ejemplos de subprocesos de trabajo.Tasks such as recalculation and background printing are good examples of worker threads. En este tema se detallan los pasos necesarios para crear un subproceso de trabajo.This topic details the steps necessary to create a worker thread. Contenido de los temas:Topics include:

La creación de un subproceso de trabajo es una tarea relativamente simple.Creating a worker thread is a relatively simple task. Solo se requieren dos pasos para que se ejecute el subproceso: implementar la función de control e iniciar el subproceso.Only two steps are required to get your thread running: implementing the controlling function and starting the thread. No es necesario derivar una clase de CWinThread.It is not necessary to derive a class from CWinThread. Puede derivar una clase si necesita una versión especial de CWinThread , pero no es necesaria para la mayoría de los subprocesos de trabajo sencillos.You can derive a class if you need a special version of CWinThread, but it is not required for most simple worker threads. Puede utilizar CWinThread sin modificaciones.You can use CWinThread without modification.

Iniciar el subprocesoStarting the Thread

Hay dos versiones sobrecargadas de AfxBeginThread : una que solo puede crear subprocesos de trabajo y otra que puede crear subprocesos de interfaz de usuario y subprocesos de trabajo.There are two overloaded versions of AfxBeginThread: one that can only create worker threads, and one that can create both user-interface threads and worker threads. Para comenzar la ejecución del subproceso de trabajo con la primera sobrecarga, llame a AfxBeginThready proporcione la siguiente información:To begin execution of your worker thread using the first overload, call AfxBeginThread, providing the following information:

  • Dirección de la función de control.The address of the controlling function.

  • Parámetro que se va a pasar a la función controladora.The parameter to be passed to the controlling function.

  • Opta Prioridad deseada del subproceso.(Optional) The desired priority of the thread. El valor predeterminado es la prioridad normal.The default is normal priority. Para obtener más información sobre los niveles de prioridad disponibles, vea SetThreadPriority en el Windows SDK.For more information about the available priority levels, see SetThreadPriority in the Windows SDK.

  • (Opcional) El tamaño de pila deseado para el subproceso.(Optional) The desired stack size for the thread. El valor predeterminado para el tamaño de pila es el mismo que el del subproceso creador.The default is the same size stack as the creating thread.

  • (Opcional) CREATE_SUSPENDED si se desea crear el subproceso en el estado suspendido.(Optional) CREATE_SUSPENDED if you want the thread to be created in a suspended state. El valor predeterminado es 0, es decir, iniciar el subproceso normalmente.The default is 0, or start the thread normally.

  • (Opcional) Los atributos de seguridad deseados.(Optional) The desired security attributes. El valor predeterminado es el mismo acceso que el de su subproceso primario.The default is the same access as the parent thread. Para obtener más información acerca del formato de esta información de seguridad, vea SECURITY_ATTRIBUTES en el Windows SDK.For more information about the format of this security information, see SECURITY_ATTRIBUTES in the Windows SDK.

AfxBeginThread crea e inicializa un CWinThread objeto, lo inicia y devuelve su dirección para que pueda hacer referencia a él más adelante.AfxBeginThread creates and initializes a CWinThread object for you, starts it, and returns its address so you can refer to it later. Se realizan comprobaciones en todo el procedimiento para asegurar que todos los objetos queden desasignados correctamente en caso de error en algún momento del proceso de creación.Checks are made throughout the procedure to make sure all objects are deallocated properly should any part of the creation fail.

Implementar la función controladoraImplementing the Controlling Function

La función controladora define el subproceso.The controlling function defines the thread. Cuando se especifica esta función, el subproceso se inicia y, cuando se cierra, finaliza el subproceso.When this function is entered, the thread starts, and when it exits, the thread terminates. Esta función debe tener el prototipo siguiente:This function should have the following prototype:

UINT MyControllingFunction( LPVOID pParam );

El parámetro es un valor único.The parameter is a single value. El valor que la función recibe en este parámetro es el valor que se pasó al constructor cuando se creó el objeto de subproceso.The value the function receives in this parameter is the value that was passed to the constructor when the thread object was created. La función controladora puede interpretar este valor de cualquier manera que elija.The controlling function can interpret this value in any manner it chooses. Se puede tratar como un valor escalar o un puntero a una estructura que contiene varios parámetros, o bien se puede omitir.It can be treated as a scalar value or a pointer to a structure containing multiple parameters, or it can be ignored. Si el parámetro hace referencia a una estructura, se puede usar la estructura no solo para pasar datos del llamador al subproceso, sino también para devolver datos del subproceso al llamador.If the parameter refers to a structure, the structure can be used not only to pass data from the caller to the thread, but also to pass data back from the thread to the caller. Si utiliza una estructura de este tipo para devolver datos al llamador, el subproceso debe notificar al llamador cuando los resultados estén listos.If you use such a structure to pass data back to the caller, the thread needs to notify the caller when the results are ready. Para obtener información sobre cómo comunicarse desde el subproceso de trabajo al llamador, vea multithreading: sugerencias de programación.For information about communicating from the worker thread to the caller, see Multithreading: Programming Tips.

Cuando finaliza la función, debe devolver un valor UINT que indique el motivo de la terminación.When the function terminates, it should return a UINT value indicating the reason for termination. Normalmente, este código de salida es 0 para indicar que se ha realizado correctamente con otros valores que indican distintos tipos de errores.Typically, this exit code is 0 to indicate success with other values indicating different types of errors. Esto es exclusivamente dependiente de la implementación.This is purely implementation dependent. Algunos subprocesos pueden mantener los recuentos de uso de los objetos y devolver el número actual de usos de ese objeto.Some threads might maintain usage counts of objects and return the current number of uses of that object. Para ver cómo las aplicaciones pueden recuperar este valor, vea multithreading: finalizar subprocesos.To see how applications can retrieve this value, see Multithreading: Terminating Threads.

Hay algunas restricciones sobre lo que puede hacer en un programa multiproceso escrito con la biblioteca MFC.There are some restrictions on what you can do in a multithreaded program written with the MFC library. Para obtener descripciones de estas restricciones y otras sugerencias sobre el uso de subprocesos, vea multithreading: sugerencias de programación.For descriptions of these restrictions and other tips about using threads, see Multithreading: Programming Tips.

Ejemplo de la función de controlControlling Function Example

En el ejemplo siguiente se muestra cómo definir una función de control y utilizarla desde otra parte del programa.The following example shows how to define a controlling function and use it from another portion of the program.

UINT MyThreadProc( LPVOID pParam )
{
    CMyObject* pObject = (CMyObject*)pParam;

    if (pObject == NULL ||
        !pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
    return 1;   // if pObject is not valid

    // do something with 'pObject'

    return 0;   // thread completed successfully
}

// inside a different function in the program
.
.
.
pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);
.
.
.

¿Qué más desea saber?What do you want to know more about?

Consulta tambiénSee also

Subprocesamiento múltiple con C++ y MFCMultithreading with C++ and MFC