逐步解說:改寫現有程式碼以使用輕量型工作
本主題說明如何將使用 Windows API 來建立和執行執行緒的現有程式碼,改寫為使用輕量型工作。
「輕量型工作」(Lightweight Task) 是指您直接從 Concurrency::Scheduler 或 Concurrency::ScheduleGroup 物件排定的工作。 當您改寫現有程式碼以使用並行執行階段的排程功能時,輕量型工作非常有用。
必要條件
在開始這個逐步解說之前,請先閱讀工作排程器 (並行執行階段) 主題。
範例
說明
下列範例說明使用 Windows API 來建立和執行執行緒的一般用法。 這個範例會使用 CreateThread 函式在個別的執行緒上呼叫 MyThreadFunction。
程式碼
// 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;
}
註解
這個範例會產生下列輸出。
Parameters = 50, 100
下列步驟顯示如何改寫這個程式碼範例以使用並行執行階段來執行相同的工作。
若要改寫這個範例以使用輕量型工作
加入標頭檔 concrt.h 的 #include 指示詞。
#include <concrt.h>
加入 Concurrency 命名空間的 using 指示詞。
using namespace Concurrency;
將 MyThreadFunction 的宣告變更為使用 __cdecl 呼叫慣例並傳回 void。
void __cdecl MyThreadFunction(LPVOID param);
修改 MyData 結構以包含 Concurrency::event 物件,這個物件會對主應用程式發出工作已完成的信號。
typedef struct MyData { int val1; int val2; event signal; } MYDATA, *PMYDATA;
以 Concurrency::CurrentScheduler::ScheduleTask 方法呼叫取代 CreateThread 方法呼叫。
CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
以 Concurrency::event::wait 方法呼叫取代 WaitForSingleObject 方法呼叫,以等候工作完成。
// Wait for the task to finish. pData->signal.wait();
移除 CloseHandle 呼叫。
變更 MyThreadFunction 之定義的簽章,以符合步驟 3。
void __cdecl MyThreadFunction(LPVOID lpParam)
在 MyThreadFunction 函式的結尾,呼叫 Concurrency::event::set 方法以對主應用程式發出工作已完成的信號。
pData->signal.set();
從 MyThreadFunction 中移除 return 陳述式。
範例
說明
下列已完成的範例顯示使用輕量型工作來呼叫 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();
}