Procedura dettagliata: adattamento del codice esistente per l'utilizzo delle attività leggere
In questo argomento viene illustrato come adattare il codice esistente che utilizza l'API Windows per creare ed eseguire un thread per utilizzare un'attività leggera.
A attività leggero è un'attività che è possibile pianificare direttamente da un concurrency::Scheduler o concurrency::ScheduleGroup oggetto.Le attività leggere sono utili quando si adatta il codice esistente per utilizzare la funzionalità di pianificazione del runtime di concorrenza.
Prerequisiti
Prima di iniziare questa procedura dettagliata, leggere l'argomento Utilità di pianificazione (runtime di concorrenza).
Esempio
Descrizione
Nell'esempio seguente viene illustrato l'utilizzo tipico dell'API Windows per creare ed eseguire un thread.In questo esempio viene utilizzata la funzione CreateThread per chiamare MyThreadFunction su un thread separato.
Codice
// 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;
}
Commenti
Questo esempio produce l'output che segue.
Parameters = 50, 100
Nei passaggi seguenti viene illustrato come adattare l'esempio di codice per l'utilizzo del runtime di concorrenza per eseguire la stessa attività.
Per adattare l'esempio per l'utilizzo di un'attività leggera
Aggiungere una direttiva #include per file di intestazione concrt.h.
#include <concrt.h>
Aggiungere una direttiva using per lo spazio dei nomi concurrency.
using namespace concurrency;
Modificare la dichiarazione di MyThreadFunction in modo da utilizzare la convenzione di chiamata __cdecl e restituire void.
void __cdecl MyThreadFunction(LPVOID param);
Modificare il MyData struttura per includere un concurrency::event oggetto segnala all'applicazione principale che l'attività è terminata.
typedef struct MyData { int val1; int val2; event signal; } MYDATA, *PMYDATA;
Sostituire la chiamata a CreateThread con una chiamata di concurrency::CurrentScheduler::ScheduleTask metodo.
CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
Sostituire la chiamata a WaitForSingleObject con una chiamata di concurrency::event::wait metodo per attendere la fine dell'attività.
// Wait for the task to finish. pData->signal.wait();
Rimuovere la chiamata a CloseHandle.
Modificare la firma della definizione di MyThreadFunction in modo da corrispondere al passaggio 3.
void __cdecl MyThreadFunction(LPVOID lpParam)
Alla fine del MyThreadFunction funzione, chiamare il concurrency::event::set metodo per segnalare all'applicazione principale che l'attività è terminata.
pData->signal.set();
Rimuovere l'istruzione return da MyThreadFunction.
Esempio
Descrizione
Nell'esempio completato seguente viene illustrato il codice che utilizza un'attività leggera per chiamare la funzione MyThreadFunction.
Codice
// 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();
}