_beginthreadex() 함수 : 스래스 생성하기
uintptr_t _beginthreadex( // 스레드 핸들 값 반환 void *security, // SECURITY_ATTRIBUTES 구조체의 포인터 변수, NULL을 사용 unsigned stack_size, // 스레드를 위한 스택의 크기, 0을 사용 unsigned ( *start_address )( void * ), // 스레드를 실행할 함수 이름 void *arglist, // 스레드 함수에 전달될 매개변수 주소 unsigned initflag, // 스레드 상태 지정 값으로 실행하기 위해 0을 사용 unsigned *thrdaddr // 스레드 ID를 받기 위한 32비트 포인터 변수, NULL을 사용 ); |
_endthreadex() 함수 : 스레드 종료하기
void _endthreadex( unsigned retval // 반환을 원하는 값 ); |
CloseHandle() 함수 : 스레드 정리하기
BOOL WINAPI CloseHandle( HANDLE hObject ); |
멀티스레드 프로그램 작성하기
#include <windows.h> #include <TCHAR.H> #include <process.h> #include <time.h> HWND hwnd; // WinMain() 함수의 지역변수를 전역변수로 전환 LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; WNDCLASS WndClass; WndClass.style = CS_HREDRAW | CS_VREDRAW; WndClass.lpfnWndProc = WndProc; WndClass.cbClsExtra= 0; WndClass.cbWndExtra= 0; WndClass.hInstance = hInstance; WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); WndClass.lpszMenuName = NULL; WndClass.lpszClassName = _T("Window Class Name"); RegisterClass(&WndClass); hwnd = CreateWindow(_T("Window Class Name"), _T("Window Title Name"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; }
void ThreadProc() { HDC hdc; int i; srand((unsigned)time(0)); hdc = GetDC(hwnd); SelectObject(hdc, CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256) ) ); // 색상을 가지는 브러시 for (i = 0; i <= 10; i++) { int num; num = rand()%500; // 0 ~ 499까지의 임의의 수 Sleep(3000); // 3초 멈춤 Rectangle(hdc, 0, 0, 20, num); } ReleaseDC(hwnd, hdc); return; }
#define THREAD_NUM 10 LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { static HANDLE hThread[THREAD_NUM]; int i; switch (iMsg) { case WM_LBUTTONDOWN: for (i = 0; i < THREAD_NUM; i++) // THREAD_NUM 10 { hThread[i] = (HANDLE)_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void *))ThreadProc, NULL, 0, NULL); Sleep(2000); } break; case WM_DESTROY: for (i = 0; i < THREAD_NUM; i++) CloseHandle(hThread[i]); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, iMsg, wParam, lParam); } |
실행 결과]
스레드 함수에 매개변수 전달하기
void ThreadProc(void *arg) { HDC hdc; int i; int xPos = *((int *)arg); srand((unsigned)time(0)); hdc = GetDC(hwnd); SelectObject(hdc, CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256) ) ); for(i = 0; i <= 10; i++) { int num; num = rand()%500; Sleep(3000); Rectangle(hdc, xPos, 0, xPos+20, num); } ReleaseDC(hwnd, hdc); return; }
#define THREAD_NUM 10 LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { static HANDLE hThread[THREAD_NUM]; static int xPos[THREAD_NUM]; int i;
switch (iMsg) { case WM_CREATE: for (i = 0; i < THREAD_NUM; i++) xPos[i] = i*100; break; case WM_LBUTTONDOWN: for (i = 0; i<THREAD_NUM; i++) { hThread[i] = (HANDLE)_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void *))ThreadProc, Sleep(2000); } break; case WM_DESTROY: for (i = 0; i < THREAD_NUM; i++) CloseHandle(hThread[i]); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, iMsg, wParam, lParam); } |
실행 결과]
스레드 동기화하기
전역번수의 영향을 알아보기
int max; void ThreadProc(void *arg) { HDC hdc; int i; int xPos = *((int *)arg); srand((unsigned)time(0)); hdc = GetDC(hwnd); SelectObject(hdc, CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256) ) );
for(i = 0; i <= 10; i++) { int num; num = rand() % 500; if (num > max) { Sleep(3000); max = num; Rectangle(hdc, xPos, 0, xPos+20, num); } } ReleaseDC(hwnd, hdc); return; }
#define THREAD_NUM 10 LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { static HANDLE hThread[THREAD_NUM]; static int xPos[THREAD_NUM]; int i;
switch (iMsg) { case WM_CREATE: for (i = 0; i < THREAD_NUM; i++) xPos[i] = i*100; max = 0; break; case WM_LBUTTONDOWN: for (i = 0; i < THREAD_NUM; i++) { hThread[i] = (HANDLE)_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void *))ThreadProc, (void *)&xPos[i], 0, NULL ); Sleep(2000); } break; case WM_DESTROY: for (i = 0; i < THREAD_NUM; i++) CloseHandle(hThread[i]); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, iMsg, wParam, lParam); } |
실행 결과]
CreateEvent() 함수 : 이벤트 생성하기
HANDLE CreateEvent( // 이벤트 핸들 값 반환 LPSECURITY_ATTRIBUTES lpEventAttributes, // 보안속성, 보통은 NULL 사용 BOOL bManualReset, // 시그널/넌시그널 수동 변환 설정 BOOL bInitialState, // 초기상태(TRUE : 시그널 상태로 이벤트 생성, FALSE : 넌시그널 상태로 이벤트 생성) LPTSTR lpName // 이벤트 이름, 보통은 NULL 사용 ); |
시그널 이란: 특정 이벤트가 발생했을때 신호를 보내서 알려주는걸 시그널이라고 한다.
시그널 : 스레드나 프로세스가 종료된 상태
넌 시그널 : 스레드나 프로세스가 실행중인 상태
SetEvent() 함수 : 이벤트 설정하기
SetEvent( // 이벤트 시그널 상태로 변환 HANDLE hEvent // 이벤트 핸들 ); |
ResetEvent() 함수 : 이벤트 재설정(리셋)하기
BOOL ResetEvent( // 이벤트를 넌시그널 상태로 변환 HANDLE hEvent // 이벤트 핸들 ); |
WaitForSingleObject() 함수 : 단일 개체 대기하기
DWORD WaitForSingleObject( HANDLE hHandle, // 대기할 개체의 핸들 DWORD dwMilliseconds // 대기 시간, INFINITE는 무한정 대기 ); |
WaitForMultipleObjects() 함수 : 복수 객체 대기하기
DWORD WaitForMultipleObjects( DWORD nCount, // 대기할 개체의 개수 const HANDLE *lpHandles, // 기다릴 개체들의 핸들 BOOL bWaitall, // 대기할 개체가 모두 기다려야 하는지 여부 // TRUE : 모든 개체가 시그널 상태가 되기를 대기 // FALSE : 1개의 객체라도 시그널 상태가 되기를 대기 DWORD dwMilliseconds // 대기 시간 ); |
이벤트 이용하기
HANDLE hEvent; int max; void ThreadProc(void *arg) { HDC hdc; int i; int *pX = (int *)arg; srand((unsigned)time(0)); hdc = GetDC(hwnd); SelectObject(hdc, CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256) ) ); for(i = 0; i <= 10; i++) { int num; WaitForSingleObject(hEvent, INFINITE); // 첫 번째 매개변수에 주어진 이벤트 개체 값이 시그널 상태이면 진행하고 num = rand()%500; if (num > max) { Sleep(3000); max = num; Rectangle(hdc, *pX, 0, *pX+20, num); } SetEvent(hEvent); } ReleaseDC(hwnd, hdc); return; }
#define THREAD_NUM 10 LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { static HANDLE hThread[THREAD_NUM]; static int xPos[THREAD_NUM]; int i;
switch (iMsg) { case WM_CREATE: for (i = 0; i < THREAD_NUM; i++) xPos[i] = i*100; max = 0; break; case WM_LBUTTONDOWN: hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); for (i=0; i<THREAD_NUM; i++) { hThread[i] = (HANDLE)_beginthreadex( NULL, 0, (unsigned int(__stdcall *)(void *))ThreadProc, (void *)&xPos[i], 0, NULL ); Sleep(2000); } WaitForMultipleObjects(THREAD_NUM, hThread, TRUE, INFINITE); CloseHandle(hEvent); break; case WM_DESTROY: for (i = 0; i < THREAD_NUM; i++) CloseHandle(hThread[i]); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, iMsg, wParam, lParam); } |
실행 결과]
'프로그램언어 > C++' 카테고리의 다른 글
c++ 표준 라이브러리 array (0) | 2022.07.06 |
---|---|
윈도우 프로그램기초예제 (0) | 2021.06.08 |
윈도우 소켓2 (0) | 2021.01.13 |
윈도우 소켓1 (0) | 2021.01.12 |
파일 입출력2 (0) | 2021.01.11 |