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 aquella 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.
Ejemplo
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 inicial
// 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;
}
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 nombresconcurrency
.
using namespace concurrency;
- Cambie la declaración de
MyThreadFunction
pasa usar la convención de llamada__cdecl
y devolvervoid
.
void __cdecl MyThreadFunction(LPVOID param);
- Modifique la estructura de
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
por una llamada al método concurrency::CurrentScheduler::ScheduleTask.
CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
- Reemplace la llamada a
WaitForSingleObject
por 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
deMyThreadFunction
.
Código completo
En el siguiente ejemplo completo se muestra código que usa una tarea ligera para llamar a la función MyThreadFunction
.
// 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();
}