연습: 간단한 작업을 사용하기 위해 기존 코드 조정
이 항목에서는 Windows API를 사용하는 기존 코드를 조정하여 간단한 작업을 사용할 스레드를 만들고 실행하는 방법을 보여 줍니다.
간단한 작업은 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;
__cdecl 호출 규칙을 사용하고 void를 반환하도록 MyThreadFunction 선언을 변경합니다.
void __cdecl MyThreadFunction(LPVOID param);
작업이 끝났음을 주 응용 프로그램에 알리는 Concurrency::event 개체를 포함하도록 MyData 구조체를 수정합니다.
typedef struct MyData { int val1; int val2; event signal; } MYDATA, *PMYDATA;
CreateThread에 대한 호출을 Concurrency::CurrentScheduler::ScheduleTask 메서드에 대한 호출로 대체합니다.
CurrentScheduler::ScheduleTask(MyThreadFunction, pData);
WaitForSingleObject에 대한 호출을 Concurrency::event::wait 메서드에 대한 호출로 대체하여 작업이 끝나기를 기다립니다.
// Wait for the task to finish. pData->signal.wait();
CloseHandle에 대한 호출을 제거합니다.
3단계와 일치하도록 MyThreadFunction 정의의 시그니처를 변경합니다.
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();
}