#define WINAPI __stdcall
__stdcall | 함수 인자를 제거하는 것이 함수 안에서 수행함을 지시 |
__cdecl | 호출한 곳에서 함수에 전달한 인자를 스택으로부터 제거 |
CALLBACK | 메시지 프로시저, asynchronous procedure call 시 주로 사용 |
WINAPI | Win32 API 원형, 스레드 시작 함수에 사용 |
APIENTRY | WinMain 선언시 사용 |
Thread 관련 함수
Thread 예외처리
MFC Thread
Worker Thread
UI Thread
Fiber 스레드 안의 스레드 (Light Weight Thread)
TLS (Thread Local Storage)
1. Win32 TLS
2. 컴파일러 지원 TLS
3. MFC TLS
Thread Synchronization (동기화) - 기본
Interlocked~
Volatile
Thread Synchronization (동기화) - Win32
1.Critical Section
2.Event
3.Semaphore
4.Mutex
Thread Synchronization (동기화) - MFC
1. CSyncObject
2. CCriticalSection
3. CSemaphore
4. CMutex
5. CEvent
6. CSingleLock
7. CMultiLock
Windows Scheduler
Quentum(퀀텀)
우선순위
기타
|
DWORD WINAPI ThreadProc(LPVOID lpParameter);
HANDLE WINAPI CreateThread(
__in LPSECURITY_ATTRIBUTES lpThreadAttributes,
//스레드 커널 객체 핸들을 자식프로세스와 공유여부 (필요 없으면 NULL)
__in SIZE_T dwStackSize,
//stack size 지정(0이면 링커 옵션의 reserve,commit 사용)
__in LPTHREAD_START_ROUTINE lpStartAddress,
//ThreadProc 함수 지정
__in LPVOID lpParameter,
//ThreadProc 함수의 인자값
__in DWORD dwCreationFlags,
//Thread 생성 상태. 0 또는 CREATE_SUSPENDED
__out LPDWORD lpThreadId
//생성된 Thread의 ID 값 (시스템 전체에서 유일)
);
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)val, 0, &dwId);
SuspendThread(hThread);
Thread 일지 중지
실패시 0xFFFFFFFF 리턴, 성공시 SuspendThread 호출 횟수 리턴
ResumeThread(hThread);
Thread 재시작
실패시 0xFFFFFFFF 리턴, 성공시 (SuspendThread 호출 횟수 -1) 리턴하며 0일 경우 재시작
SwitchToThread();
컨텍스트 스위칭을 일으킴
Sleep(0)과 동일. 성공시 nonzero, 실패시 zero
Thread 종료 대기 방법1 : STILL_ACTIVE 체크
DWORD dwExitCode;
while (GetExitCodeThread(hThread, &dwExitCode) && dwExitCode == STILL_ACTIVE)
Sleep(100); //종료 대기
Thread 종료 대기 방법2 : WaitForSingleObject 또는 WaitForMultipleObjects
WaitForSingleObject(hThread, INFINITE);
WaitForMultipleObjects(1, &hThread, TRUE, INFINITE);
ExitThread(0);
Thread 강제 종료 방법1 : 비권장
TerminateThread(GetCurrentThread(), 0);
Thread 강제 종료 방법2 : 비권장
CloseHandle(hThread);
|
** thread 함수 사용.cpp
#include <windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
int val = (int)lpParameter;
cout << "[Thread] lpParameter : " << val << endl;
/*
Thread 강제 종료 방법1 : 비권장
*/
ExitThread(0);
/*
Thread 강제 종료 방법2 : 비권장
*/
TerminateThread(GetCurrentThread(), 0);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
setlocale(LC_ALL, "");
int val = 3;
DWORD dwId;
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)val, 0, &dwId);
if (hThread == NULL)
wcout << TEXT("CreateThread Failed") << endl;
else
{
int suspendCount;
Sleep(100);
/*
생성된 Thread의 ID 값 (시스템 전체에서 유일)
*/
cout << "dwId : " << dwId << endl;
/*
SuspendThread : Thread 일지 중지
실패시 0xFFFFFFFF 리턴, 성공시 SuspendThread 호출 횟수 리턴
*/
suspendCount = SuspendThread(hThread);
cout << "suspendCount : " << suspendCount << endl;
/*
ResumeThread : Thread 재시작
실패시 0xFFFFFFFF 리턴, 성공시 (SuspendThread 호출 횟수 -1) 리턴하며 0일 경우 재시작
*/
suspendCount = ResumeThread(hThread);
cout << "suspendCount : " << suspendCount << endl;
/*
SwitchToThread() : 컨텍스트 스위칭을 일으킴
Sleep(0)과 동일. 성공시 nonzero, 실패시 zero
*/
BOOL bContextSwitch = SwitchToThread();
if (bContextSwitch)
cout << "occured context switch : " << bContextSwitch << endl;
else
cout << "not occured context switch : " << bContextSwitch << endl;
/*
Thread 종료 대기 방법1
STILL_ACTIVE 체크
*/
DWORD dwExitCode;
while (GetExitCodeThread(hThread, &dwExitCode) && dwExitCode == STILL_ACTIVE)
{
Sleep(100); //종료 대기
}
/*
Thread 종료 대기 방법2
WaitForSingleObject 또는 WaitForMultipleObjects 사용
*/
WaitForSingleObject(hThread, INFINITE);
WaitForMultipleObjects(1, &hThread, TRUE, INFINITE);
CloseHandle(hThread);
}
return 0;
}
|
UINT WINAPI ThreadProc(LPVOID lpParameter)
{
return 0;
}
void main()
{
//MFC 아닌 경우 #define _MT, #include <process.h> 필요 할 수 있음.
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, (void*)GetSafeHwnd(), 0, NULL);
}
|
#include <windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;
DWORD WINAPI ThreadProc(LPVOID lpParameter);
DWORD InnerThreadProc(LPVOID lpParameter);
DWORD HandleException(LPEXCEPTION_POINTERS p);
long g_lThreadCnt = 0;
BOOL g_bExitThread = FALSE;
int _tmain(int argc, _TCHAR* argv[])
{
__try
{
//do something
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)3, NULL, NULL);
CloseHandle(hThread);
}
__except (HandleException(GetExceptionInformation())) //예외정보 HandleException로 전달
{
//do something
}
//실행된 Thread의 정상종료 대기
g_bExitThread = TRUE;
while (0 < g_lThreadCnt)
Sleep(200);
return 0;
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
__try
{
InterlockedIncrement(&g_lThreadCnt);
__try
{
return InnerThreadProc(lpParameter);
}
__except (HandleException(GetExceptionInformation())) //예외정보 HandleException로 전달
{
//do something
}
}
__finally
{
InterlockedDecrement(&g_lThreadCnt);
}
return 0;
}
DWORD InnerThreadProc(LPVOID lpParameter)
{
//do something
while (true)
{
if (g_bExitThread)
break;
}
return 0;
}
DWORD HandleException(LPEXCEPTION_POINTERS p)
{
//예외 로깅 등 추적 정보 처리
//LPEXCEPTION_POINTERS 를 통해 Exception 확인
PEXCEPTION_RECORD ExceptionRecord = p->ExceptionRecord; //예외에 대한 정보
PCONTEXT ContextRecord = p->ContextRecord; //프로세서의 레지스터 데이터 및 프로세서 종속적인 정보
ExceptionRecord->ExceptionCode; //예외코드
ExceptionRecord->ExceptionAddress; //예외발생 주소
//예외 처리 필터
return EXCEPTION_EXECUTE_HANDLER; //__except 블록 실행을 유도
}
|
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
UINT ThreadProc(LPVOID lpParameter); //Worker Thread 함수 정의
|
UINT ThreadProc(LPVOID lpParameter) { return 0; } void 쓰레드생성하는 함수() { CWinThread* pThread = AfxBeginThread(ThreadProc, 3); } |
CWinThread* AfxBeginThread(
CRuntimeClass* pThreadClass,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
|
//UIThread.h
#pragma once
#include "afxwin.h"
class CUIThread : public CWinThread
{
DECLARE_DYNCREATE(CUIThread);
public:
CUIThread(void);
~CUIThread(void);
virtual BOOL InitInstance();
virtual BOOL PreTranslateMessage(MSG* pMsg);
};
|
//UIThread.cpp
#include "StdAfx.h"
#include "UIThread.h"
#include "TestWnd.h"
IMPLEMENT_DYNCREATE(CUIThread , CWinThread);
CUIThread::CUIThread(void) {}
CUIThread::~CUIThread(void){}
BOOL CUIThread::InitInstance()
{
CTestWnd* pFrame = new CTestWnd;
pFrame->Create(NULL, _T("UI스레드 윈도우"));
pFrame->ShowWindow(SW_SHOW);
m_pMainWnd = pFrame;
return TRUE;
//return CWinThread::InitInstance();
}
//메세지 처리시 정의
BOOL CUIThread::PreTranslateMessage(MSG* pMsg)
{
if (CWinThread::PreTranslateMessage(pMsg)) return TRUE;
switch(pMsg->message) {
case WM_LBUTTONDOWN:
MessageBox(pMsg->hwnd, _T("hi~"), _T("hi caption"), MB_OKCANCEL);
return TRUE;
}
return FALSE;
}
|
//TestWnd.h
#pragma once
#include "afxwin.h"
class CTestWnd : public CFrameWnd
{
public:
CMyframeWnd(void);
~CMyframeWnd(void);
};
|
//TextWnd.cpp
#include "StdAfx.h"
#include "TestWnd.h"
CTestWnd::CMyframeWnd(void) {}
CTestWnd::~CMyframeWnd(void) {}
|
#include "UITHREAD.h" ... AfxBeginThread(RUNTIME_CLASS(CUIThread)); |
**. UI Thread 인자 전달 방법
suspend로 thread 생성후 멤버 변수 값 세팅으로 인자 전달.
CUIThread* pThread = (CUIThread*)AfxBeginThread(RUNTIME_CLASS(CUIThread),
THREAD_PRIORITY,NORMAL, 0,
CREATE_SUSPENDED);
if (pThread)
{
pThread->lpParameter = 인자 값;
pThread->ResumeThread();
}
TLS 할당 : DWORD TlsAlloc(void); //성공 : 0~TLS index, 실패 : TLS_OUT_OF_INDEXES(0xFFFFFFFF)
TLS 해제 : BOOL TlsFree(DWORD dwTlsIndex); //성공 : nonzero, 실패 : zero
TLS 값 지정 : BOOL TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue); //성공 : nonzero, 실패 : zero
TLS 값 얻기 : LPVOID TlsGetValue(DWORD dwTlsIndex);
|
#include <windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;
long g_lThreadCnt = 0;
DWORD g_dwTls = TLS_OUT_OF_INDEXES;
void InnerTreadProc(void)
{
int val = (int)TlsGetValue(g_dwTls);
TCHAR tmp[100];
wsprintf(tmp, _T("TLS val : %d\n"), val);
wcout << tmp;
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
__try
{
InterlockedIncrement(&g_lThreadCnt);
TlsSetValue(g_dwTls, lpParameter);
InnerTreadProc();
}
__finally
{
InterlockedDecrement(&g_lThreadCnt);
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
g_dwTls = TlsAlloc();
for (int i=0; i<10; i++)
{
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)i, 0, NULL);
if (hThread) CloseHandle(hThread);
}
while (0 < g_lThreadCnt) Sleep(200);
TlsFree(g_dwTls);
return 0;
}
|
#include <windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;
long g_lThreadCnt = 0;
__declspec(thread) int intTLS = 0;
void InnerTreadProc(void)
{
TCHAR tmp[100];
wsprintf(tmp, _T("TLS val : %d\n"), intTLS);
wcout << tmp;
}
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
__try
{
g_lThreadCnt++;
intTLS = (int)lpParameter;
InnerTreadProc();
}
__finally
{
g_lThreadCnt--;
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
for (int i=0; i<10; i++)
{
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)i, 0, NULL);
if (hThread) CloseHandle(hThread);
}
while (0 < g_lThreadCnt) Sleep(200);
return 0;
}
|
... 생략 ... int cnt = 1;
class CMFCTLS : public CNoTrackObject
{
public :
HWND hWnd;
int val;
};
THREAD_LOCAL(CMFCTLS, g_MFCTLS) //g_MFCTLS라는 변수가 MFC TLS로 선언됨
void InnerThreadProc(void)
{
TCHAR msg[100];
wsprintf(msg, _T("hi~ val : %d"), g_MFCTLS->val); //TLS 값 사용
MessageBox(g_MFCTLS->hWnd, msg, _T("caption"), MB_OK); //TLS 값 사용
}
UINT ThreadProc(LPVOID lpParameter)
{
g_MFCTLS->hWnd = (HWND)lpParameter; //TLS 값 세팅
g_MFCTLS->val = cnt++; //TLS 값 세팅
InnerThreadProc();
return 0;
}
void 쓰레드생성하는 함수()
{
for (int i=0; i<3; i++)
AfxBeginThread(ThreadProc, (LPVOID)GetSafeHwnd());
}
|
LONG InterlockedIncrement(LONG volatile& lpAddend);
//동작 : lpADdend++, return : 증감 이전 값
LONG InterlockedDecrement(LONG volatile& lpAddend);
//동작 : lpADdend--, return : 증감 이전 값
LONG InterlockedExchangeAdd(LPLONG volatile Addend, LONG value);
//동작 : Addend += value, return : 증감 이전 값
LONG InterlockedExchange(LONG volatile* Target, LONG value);
//동작 : Target = value, return : 이전 값
LONG InterlockedCompareExchange(LONG volatile* Destination, LONG Exchange, LONG Comperand);
//동작 : if (*Destination == Comperand) *Destination = Exchange;, return : 이전 값
PVOID InterlockedExchangePointer(PVOID volatile* Target, PVOID value);
//동작 : Target = value, return : 이전 포인터
PVOID InterlockedCompareExchangePointer(PVOID volatile* Destination, PVOID Exchange, PVOID Comperand);
//동작 : if (Destination == Comperand) Destination = Exchange, return : 이전 포인터
|
volatile bool isRun = true;
while (isRun)
{
wcout << _T("running..");
}
|
**. EnterCiriticalSection()은 lock을 소유하지 못하면 최대 30일 동안 대기 한다. 이것을 회피하기 위해 TryEnterCriticalSection()이 제공되며 lock을 소유하지 못할 경우 FALSE를 리턴한다.
EnterCriticalSection(&g_cs); // lock : 최대 30일동안 대기 (중복소유)
LeaveCriticalSection(&g_cs); // lock 해제 (중복소유)
HANDLE g_hEvent = NULL;
void main()
{
g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
_beginthreadex(...); //thread 실행
SetEvent(g_hEvent);
CloseHandle(g_hEvent);
}
UINT WINAPI ThreadProc(LPVOID lpParameter)
{
..
MSG msg;
while (true)
{
DWORD dw = MsgWaitForMultipleObjects(1, &g_hEvent, FALSE, INFINITE, QS_ALLINPUT);
if (dw == WAIT_OBJECT_0)
break;
else
if (dw == WAIT_OBJECT_0+1)
{
if (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
break;
}
}
..
return (DWORD) msg.wParam;
}
CCriticalSection g_cs; UINT WINAPI ThreadProc(LPVOID) // thread 함수 { g_cs.Lock(); //do somthing g_cs.Unlock(); return 0; } |
class CTryCriticalSection : public CCriticalSection { public: virtual BOOL Lock(); }; inline BOOL CTryCriticalSection::Lock() { return TryEnterCriticalSection(&m_sect); //m_sect은 CCriticalSection의 CRITICAL_SECTION object멤버 } |
CSemaphore g_se(10, 10); UINT WINAPI ThreadProc(LPVOID) // thread 함수 { g_se.Lock(); //do somthing g_se.Unlock(); return 0; } |
CMutex g_mu; UINT WINAPI ThreadProc(LPVOID) // thread 함수 { g_mu.Lock(); //do somthing g_mu.Unlock(); return 0; } |
class CTestEvent : public CEvent { public : virtual BOOL Unlock(); }; inline BOOL CTestEvent::Unlock() { return SetEvent(); } |
CMutex g_mu; UINT WINAPI ThreadProc(LPVOID) { CSingleLock sLock(&g_mu); sLock.Lock(); //something.. sLock.UnLock(); return 0; } |
CEvent g_event[10]; UINT WINAPI ThreadProc(LPVOID) { CMultiLock mLock(g_evnet, 10); DWORD dw = mLock.Lock(INFINITE, FALSE); if (WAIT_OBJECT_0 <= dw && dw < (WAIT_OBJECT_0 + 2)) { //.. mLock.Unlock(); } return 0; } |
: http://www.macdesign.net/academic/it4813/it4813-Submitted/IT4813-u03a1-Process_States.html |
'C++' 카테고리의 다른 글
Dialog 창에서 엔터나 ESC 일때 창 닫히는 현상 막기 (0) | 2010.10.13 |
---|---|
윈도우 창을 모니터 화면 가운데로 이동하기 (0) | 2010.10.13 |
Random 난수 생성하기 (0) | 2010.10.13 |
SOCKET (0) | 2010.10.09 |
자료구조 (0) | 2010.09.30 |
VC++ 수행시간 체크 (1) | 2010.09.15 |
IME(Input Method Editor) (0) | 2010.09.11 |
Visual C++ : window 생성 template (0) | 2010.09.10 |