Tutorial: Adaptar el código existente para usar tareas ligeras
En este tema se muestra cómo adaptar código existente que usa la API de Windows para crear y ejecutar un subproceso para una tarea ligera.
Una tarea ligera es una tarea que se programa directamente a partir de un objeto Concurrency::Scheduler o Concurrency::ScheduleGroup. Las tareas ligeras son útiles cuando se adapta código existente para usar la funcionalidad de programación del Runtime de simultaneidad.
Requisitos previos
Antes de empezar este tutorial, lea el tema Programador de tareas (Runtime de simultaneidad).
Ejemplo
Descripción
En el siguiente ejemplo se muestra el uso típico de la API de Windows para crear y ejecutar un subproceso. En este ejemplo se usa la función CreateThread para llamar a MyThreadFunction en un subproceso independiente.
Código
// windows-threads.cpp
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#define BUF_SIZE 255
DWORD WINAPI MyThreadFunction(LPVOID param);
// Data structure for threads to use.
typedef struct MyData {
int val1;
int val2;
} MYDATA, *PMYDATA;
int _tmain()
{
// Allocate memory for thread data.
PMYDATA pData = (PMYDATA) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(MYDATA));
if( pData == NULL )
{
ExitProcess(2);
}
// Set the values of the thread data.
pData->val1 = 50;
pData->val2 = 100;
// Create the thread to begin execution on its own.
DWORD dwThreadId;
HANDLE hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
MyThreadFunction, // thread function name
pData, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
if (hThread == NULL)
{
ExitProcess(3);
}
// Wait for the thread to finish.
WaitForSingleObject(hThread, INFINITE);
// Close the thread handle and free memory allocation.
CloseHandle(hThread);
HeapFree(GetProcessHeap(), 0, pData);
return 0;
}
DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{
PMYDATA pData = (PMYDATA)lpParam;
// Use thread-safe functions to print the parameter values.
TCHAR msgBuf[BUF_SIZE];
StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"),
pData->val1, pData->val2);
size_t cchStringSize;
StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
DWORD dwChars;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), msgBuf, (DWORD)cchStringSize, &dwChars, NULL);
return 0;
}
Comentarios
Este ejemplo produce el siguiente resultado.
Parameters = 50, 100
Los siguientes pasos muestran cómo adaptar el ejemplo de código para usar el Runtime de simultaneidad para realizar la misma tarea.
Para adaptar el ejemplo para usar una tarea ligera
Agregue una directiva #include para el archivo de encabezado concrt.h.
#include <concrt.h>
Agregue una directiva using para el espacio de nombres Concurrency.
using namespace Concurrency;
Cambie la declaración de MyThreadFunction pasa usar la convención de llamada __cdecl y devolver void.
void __cdecl MyThreadFunction(LPVOID param);
Modifique la estructura MyData para incluir un objeto Concurrency::event que indique a la aplicación principal que la tarea ha terminado.
typedef struct MyData { int val1; int val2; event signal; } MYDATA, *PMYDATA;
Reemplace la llamada a CreateThread con una llamada al método Concurrency::CurrentScheduler::ScheduleTask.
CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
Reemplace la llamada a WaitForSingleObject con una llamada al método Concurrency::event::wait para esperar a que finalice la tarea.
// Wait for the task to finish. pData->signal.wait();
Quite la llamada a CloseHandle.
Cambie la signatura de la definición de MyThreadFunction para que coincida con el paso 3.
void __cdecl MyThreadFunction(LPVOID lpParam)
Al final de la función MyThreadFunction, llame al método Concurrency::event::set para indicar a la aplicación principal que la tarea ha terminado.
pData->signal.set();
Quite la instrucción return de MyThreadFunction.
Ejemplo
Descripción
En el siguiente ejemplo completo se muestra código que usa una tarea ligera para llamar a la función MyThreadFunction.
Código
// migration-lwt.cpp
// compile with: /EHsc
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <concrt.h>
using namespace Concurrency;
#define BUF_SIZE 255
void __cdecl MyThreadFunction(LPVOID param);
// Data structure for threads to use.
typedef struct MyData {
int val1;
int val2;
event signal;
} MYDATA, *PMYDATA;
int _tmain()
{
// Allocate memory for thread data.
PMYDATA pData = (PMYDATA) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(MYDATA));
if( pData == NULL )
{
ExitProcess(2);
}
// Set the values of the thread data.
pData->val1 = 50;
pData->val2 = 100;
// Create the thread to begin execution on its own.
CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
// Wait for the task to finish.
pData->signal.wait();
// Free memory allocation.
HeapFree(GetProcessHeap(), 0, pData);
return 0;
}
void __cdecl MyThreadFunction(LPVOID lpParam)
{
PMYDATA pData = (PMYDATA)lpParam;
// Use thread-safe functions to print the parameter values.
TCHAR msgBuf[BUF_SIZE];
StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"),
pData->val1, pData->val2);
size_t cchStringSize;
StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
DWORD dwChars;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), msgBuf, (DWORD)cchStringSize, &dwChars, NULL);
pData->signal.set();
}