오늘은 쓰레드을 사용하는데 있어 일반적인 무한루프를 통해 프로세스를 처리하는 방식이 아닌
클래스기반하에 Cwnd 나 CDialog 기반하에 돌릴 수 있는 쓰레드를 만드는 방법에서 가장 심플하게 할 수 있는 방법을 소개하고 합니다.
CWinThread 을 통해서도 만드는 것도 있지만 오늘은 다른 방법으로 만들고자 합니다.
* 소스코드 (header)
#include "ProcessThread.h"
ProcessThread *mp_thread;
* 소스코드 (cpp)
mp_thread = NULL;
void CDlg::ThreadStart()
{
if(mp_thread) ThreadEnd();
mp_thread = (ProcessThread *)AfxBeginThread(RUNTIME_CLASS(ProcessThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL); //<-이 부분 추가
mp_thread->m_bAutoDelete = TRUE; // 사실 이 부분 때문에 별도의 해제 없이 종료 해도 되지만 간혹 메모리 해제가 안되는 경우가 있다.
mp_thread->SetConfiguration(m_exe_str); // 만들어진 함수.. 필요한 정보를 넣어 놓는다.
mp_thread->ResumeThread(); // 시작...
}
// 사실 이 부분 때문에 별도의 해제 없이 종료 해도 되지만 간혹 메모리 해제가 안되는 경우가 있어 종료 시 한번 해준다.
void CDlg::ThreadEnd()
{
mp_thread->EndThreadProcess();
if(mp_thread){ // 종료를 해봐도 메모리가 남아있을 경우 대시도
DWORD dwExitCode;
mp_thread->PostThreadMessage(WM_QUIT, 0, 0); /* UI 쓰레드 종료 메시지 전송 */
Sleep(100);
WaitForSingleObject(mp_thread->m_threadKillEvent, INFINITE); // 종료가 될 때 까지 기다린다.
WaitForSingleObject(mp_thread->m_hThread, INFINITE);
GetExitCodeThread(mp_thread->m_hThread, &dwExitCode );
if( dwExitCode == STILL_ACTIVE){ // 그래도 살아 있으면 강제 종료
TerminateThread(mp_thread->m_hThread,0);
}
Sleep(10);
mp_thread = NULL;
}
}
void CDlg::ThreadEnd()
{
mp_thread->Test();
}
* 소스코드 (header) // 쓰레드
#include "ProcessWnd.h"
class ProcessThread : public CWinThread
{
ProcessWnd *mp_process_wnd;
...
}
* 소스코드 (cpp) // 쓰레드
ProcessThread::ProcessThread()
{
mp_process_wnd = NULL;
}
ProcessThread::~ProcessThread()
{
m_threadKillEvent.SetEvent(); // 스레드 종료 이벤트를 발생시킵니다
}
void ProcessThread::KillThreadEvent()
{
m_threadKillEvent.SetEvent(); // 스레드 종료 이벤트를 발생시킵니다
}
BOOL ProcessThread::InitInstance()
{
mp_desk_wnd = GetMainWnd();
mp_desk_wnd = NULL;
HWND dest_hwnd = ::GetDesktopWindow();
mp_desk_wnd = CWnd::FromHandle(dest_hwnd); // 부모를 상황에 맞추어 실부모나 바탕화면 등등 설정하면 된다.
mp_process_wnd = NULL;
mp_process_wnd = new ProcessWnd();
if(mp_process_wnd){
mp_process_wnd->SetConfiguration(m_exe_str);
mp_process_wnd->Create(NULL,NULL, WS_CHILD, CRect(0,0,0,0), mp_desk_wnd, VAN_WND-1);
//mp_process_wnd->ModifyStyle(WS_CAPTION, WS_SYSMENU | WS_MINIMIZEBOX); // Event을 위한 것.,.
m_pMainWnd = mp_process_wnd;
}else{
TRACE0("Create ERR -.- !!!!");
}
return TRUE;
}
void ProcessThread::EndThreadProcess()
{
if(mp_process_wnd){
if(mp_process_wnd && ::IsWindow(mp_process_wnd->m_hWnd)){
mp_process_wnd->EndWndProcess();
if(mp_process_wnd && ::IsWindow(mp_process_wnd->m_hWnd)){
mp_process_wnd->DestroyWindow();
delete mp_process_wnd; mp_process_wnd = NULL;
}
}
//WaitForSingleObject(this->m_hThread, 1000);
}
}
위 내용은 중간중간 실제 제가 사용하는 부분을 추출하여 설명을 넣었습니다.
위 내용을 보시면 의미를 아실 수 있으며.. AfxBeginThread 이 함수를 RUNTIME_CLASS 방식으로 설정한다는 부분이 핵심입니다.
m_bAutoDelete 를 TRUE 로 하였기 때문에 사실 그냥 종료를 하면 쓰레드는 자동 해제가 됩니다. 하지만 간혹 안되는 경우가 있어 TerminateThread 를 해야 하는 경우도 존재하게 됩니다. 이 부분은 저도 왜 정상적으로 빨리 해제가 안되는지를 모르기 때문에 그냥 쓰고 있습니다.
많은 이용 바랍니다.
#c++#PostThreadMessage#WaitForSingleObject#스레드#쓰레드#클래스
'프로그램 > C++' 카테고리의 다른 글
현재 실행중인 폴더 위치 (0) | 2021.01.13 |
---|---|
Dialog 모달리스 사용하기 (0) | 2021.01.13 |
vc++에서 간단히 사용헐 수 있는 html 파싱 dll (0) | 2021.01.11 |
[MFC] 유니코드 멀티바이트 UTF-8 문자열 인코딩 변환 모음 (0) | 2021.01.10 |
WM_COPYDATA 사용하기 ( OnCopyData ) (1) | 2021.01.10 |