WindowsApi:CreateThread
Creates a thread to execute within the virtual address space of the calling process. To create a thread that runs in the virtual address space of another process, use the CreateRemoteThread function.
Prototype
Syntax:
HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in SIZE_T dwStackSize,
__in LPTHREAD_START_ROUTINE lpStartAddress,
__in_opt LPVOID lpParameter,
__in DWORD dwCreationFlags,
__out_opt LPDWORD lpThreadId
);
Parameters:
Parameters | IO | Remarks |
lpThreadAttributes | in, optional | 보안 디스크립터 |
dwStackSize | in | 초기 스텍 크기 |
lpStartAddress | in | 스레드와 연결될 함수포인터 |
lpParameter | in, optional | 스레드와 연결될 함수의 인자 |
dwCreationFlags | in | 생성 옵션 |
lpThreadId | out, optional | 스레드 ID |
Requirements:
Header | Winbase.h (include Windows.h) |
Library | Kernel32.lib |
DLL | Kernel32.dll |
함수가 성공하면 새로운 스레드 핸들을 반환하고, 실패할 경우 NULL을 반환하며 오류정보는 GetLastError()를 통하여 알 수 있다. 주의사항으로 스레드를 사용할 경우 Visual Studio의 경우 프로젝트 속성 > 구성 속성 > C/C++ > 코드 생성 > 런타임 라이브러리를 다중스레드로 적용해야 한다.
Simple Example
thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadFunc, NULL, 0, &thread_id);
CloseHandle(thread_handle);
CreateThread WARNING
CreateThread() 사용 경고. Win32 함수 ExitThread()와 CreateThread() 사용은 추천하지 않는다. 일시 중단된 스레드가 C 런타임 데이터 구조에 대한 액세스를 완료할 때까지 둘 이상의 스레드가 대기 상태로 차단되어 있는 경우 SuspendThread()를 사용하면 교착 상태가 발생할 수 있다.
올바른 스레드 종료 방법
스레드를 종료시키기 위한 바람직한 방법에 대하여 아래와 같이 설명한다.
Win32 스레드 함수 비교
- CreateThread()
- 윈도우 API로, 새로운 스레드를 생성한다. (Windows.h)
- _beginthread()
- C/C++ Runtime-Library (process.h).
- 새로운 쓰레드를 생성하고 난 후 바로 CloseHandle()를 호출하여 생성한 스레드의 핸들을 닫아버려서 스레드간 통신이 불가능하다. 핸들을 바로 닫는 이유는 Win32의 상세함을 숨기기 위함인데 결국 버그가 되어 버린 함수이다. 짝을 이루는 함수는 _endthread()이며, 생성한 스레드가 종료되면, 이 함수가 자동으로 호출된다. 따라서 이 함수는 명시하지 않으며, 할 경우 에러가 난다. 성공적으로 수행되면 새 스레드를 가리키는 핸들을 반환하고 오류가 있는 경우에는 오류 코드를 반환한다.
- _beginthreadex()
- C/C++ Runtime-Library (process.h).
- 내부적으로 새로 생성한 쓰레드의 핸들을 닫지 않기 때문에 명시적으로 _endthreadex()이며, 역시 생성된 스레드가 종료되면 자동으로 호출된다. 따라서 이 함수는 명시하지 않아도 된다. _endthreadex()를 명시해도 _endthread()처럼 에러가 나진 않는다. 성공적으로 수행되면 새 스레드를 가리키는 핸들을 반환하고 오류가 있는 경우에는 오류 코드를 반환한다.
Result
Libcmt.lib로 빌드한 프로그램에서 C 런타임 루틴을 호출하려면 _beginthread() 또는 _beginthreadex()를 사용하여 스레드를 시작해야 한다. Win32 함수 ExitThread()와 CreateThread() 사용은 추천하지 않는다. 그 이유는 #CreateThread WARNING항목 참조.
MSDN 설명
- 참조: [http://msdn.microsoft.com/ko-kr/library/7t9ha0zh(v=vs.110.aspx MSDN: 스레드 컨트롤을 위한 C 런타임 라이브러리 함수]
- LIBCMT 및 MSVCRT C 런타임 라이브러리는 스레드를 만들고 종료하기 위해 _beginthread(), _beginthreadex() 및 _endthread(), _endthreadex() 함수를 제공한다. _beginthread()와 beginthreadex()는 새 스레드를 만들고 작업이 성공하면 스레드 식별자를 반환한다. 스레드는 실행을 완료하면 자동으로 종료되거나 _endthread() 또는 _endthreadex()를 호출하여 스스로 종료할 수 있다.
- 차이점: _beginthread()와 _beginthreadex()는 Win32 API의 CreateThread()와 유사하지만 아래와 같은 차이점이 있다. 이러한 함수는 특정한 C 런타임 라이브러리 변수를 초기화한다. 이것은 스레드에 C 런타임 라이브러리를 사용하는 경우에만 의미가 있다. CreateThread()는 보안 특성을 제어한다. 이 함수를 사용하여 일시 중단된 상태에서 스레드를 시작할 수 있다.
- _beginthread()와 _beginthreadex() 함수는 새 스레드를 만든다. 스레드는 코드 및 데이터 세그먼트를 한 프로세스의 다른 스레드와 공유하지만 고유한 레지스터 값, 스택 공간 및 현재 명령 주소를 가진다. 시스템은 각 스레드에 CPU 시간을 제공하므로 프로세스의 모든 스레드가 동시에 실행될 수 있다.
- _endthread() 함수는 _beginthread()에서 만든 스레드를 종료하고, 이와 마찬가지로 _endthreadex() 함수는 _beginthreadex()에서 만든 스레드를 종료한다. 스레드는 작업이 끝나면 자동으로 종료된다. _endthread()와 _endthreadex()는 스레드 내에서 조건 종료에 유용하다. 예를 들어, 통신 포트를 제어할 수 없게 되면 통신 처리 전용 스레드를 종료할 수 있다.
See also
- Windows Api
- TerminateThread()
- ExitThread()
- SuspendThread()
- ResumeThread()
- SetThreadPriority()
- GetThreadPriority()
LIBCMT & MSVCRT C
Favorite site
- [http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85.aspx MSDN CreateThread function reference]