출처 : http://codens.info/678
쓰레드 생성
- AfxBeginThread 권장
- CWinThread::m_bAutoDelete
- 기본은 TRUE, 자동으로 개체(핸들포함)가 삭제됨 <- 권장
- FALSE로 설정하려면 CREATE_SUSPENED 로 시작해서 설정후 ResumeThread()해줘야함
- 해제시 핸들을 닫으면 안되고 CWinThread개체를 delete 해야 함
- AfxEndThread()는 강제 종료 함수로 권장 안함
- CreateThread() 권장 안함
* 쓰레드 종료 대기
- WaitForSingleObject 사용 권장
- GetExitCodeThread 는 bAutoDelete = TRUE시 문제 있음,
- CreateThread()때만 사용, 하지만 권장 안함
//=======================================
//AfxBeginThread
//시작
CWinThread * CSimpleTestDlg::MFC_TrdStart( bool _bAutoDel)
{
char *str = "MFC_TrdStart"; g_pstr[0]=str;m_pstr[0] = str;
//쓰레드 생성
m_bStop=false;
CWinThread *pWThd=0;
//
if( _bAutoDel == false){
_DbgStr(_T("MFC_TrdStart- 자동삭제=false"));
//값을 바꾸기위해서는 멈춤->설정->시작
pWThd = AfxBeginThread( MFC_TrdFunc, this, 0, 0, CREATE_SUSPENDED );//멈춤
pWThd->m_bAutoDelete = FALSE; //기본값은 TRUE, 설정
pWThd->ResumeThread();//시작
}else{
_DbgStr(_T("MFC_TrdStart- 자동삭제=true"));
pWThd = AfxBeginThread( MFC_TrdFunc, this, 0, 0, 0 );//<- 권장
}
if( !pWThd )
return 0;
m_hThread = pWThd->m_hThread;
_DbgStr(_T("MFC_TrdStart- 끝=%X"), m_hThread);
return pWThd;
}
//쓰레드 트리거 함수
UINT __cdecl CSimpleTestDlg::MFC_TrdFunc( LPVOID pParam )
{
char *str = "MFC_TrdFunc";g_pstr[1]=str;
CSimpleTestDlg *pClass = (CSimpleTestDlg *)pParam;
pClass->MFC_TrdProc();
_DbgStr(_T("쓰레드 종료 MFC_TrdFunc"));//MFC_TrdProc()에 AfxEndThread()가 있으면 여기까지 실행이 안됨
return 1;
}
//실제 쓰레드 동작
int CSimpleTestDlg::MFC_TrdProc()
{
char *str = "MFC_TrdProc";g_pstr[2]=str; m_pstr[2] = str;
while(1)
{
if( m_bStop ){
_DbgStr(_T("쓰레드 종료신호 MFC_TrdProc"));
break;
}
Sleep(1000);
_DbgStr(_T("쓰레드 실행중 MFC_TrdProc"));
}
_DbgStr(_T("쓰레드 종료 MFC_TrdProc-1-%d"), (UINT)GetTime() );
//AfxEndThread(0);//쓰레드가 강제 종료됨, 사용하면 안됨 TerminateThread()와 같음
_DbgStr(_T("쓰레드 종료 MFC_TrdProc-2-%d"), (UINT)GetTime() );//
return 1;
}
//===============================================
//쓰레드 종료를 기다린다
//WaitForSingleObject 사용 권장
// CreadThread()로 시작한 쓰레드만 대기, AfxBeginThread() 로 시작한 쓰레드는 사용하면 안됨
int WaitThreadEndH(HANDLE _hThread, int _nWaitMilSec , LPCTSTR _sMsg, bool _bClose)
{
if( !_hThread ) return 0;
_DbgStr(_T("WaitThreadEnd-시작-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
//bFinishThread == TRUE; // 종료를 위한 변수설정 후 3초간 대기
DWORD dwExit=0;
DWORD dwRetCode = WaitForSingleObject(_hThread, _nWaitMilSec);
if(dwRetCode == WAIT_OBJECT_0) // 정상종료
{
_DbgStr(_T("WaitThreadEnd-정상 종료-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
}
else if(dwRetCode == WAIT_TIMEOUT) // 타임아웃
{
//::TerminateThread(_hThread, 0 );
_DbgStr(_T("WaitThreadEnd-강제종료-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
}
if( _bClose){
//AfxBeginThread()로 생성된 쓰레드는 핸들을 닫으면 안된다. CWinThread를 delete 해야한다.
//m_bAutoDelete == TRUE 일때는 호출하면 안된다
CloseHandle( _hThread );
}
_DbgStr(_T("WaitThreadEnd-끝-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
return 1;
}
//AfxBeginThread() 로 시작한 쓰레드는 이함수로 종료해야 함
int WaitThreadEndW(CWinThread *_pWinThread, int _nWaitMilSec, LPCTSTR _sMsg)
{
if( !_pWinThread ) return 0;
HANDLE _hThread = _pWinThread->m_hThread;
_DbgStr(_T("WaitThreadEnd(W)-시작-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
//bFinishThread == TRUE; // 종료를 위한 변수설정 후 3초간 대기
bool bAutoDel = _pWinThread->m_bAutoDelete;
DWORD dwExit=0;
DWORD dwRetCode = WaitThreadEndH( _pWinThread->m_hThread, _nWaitMilSec, _sMsg, false );//핸들을 닫으면 안된다.
//m_bAutoDelete = FALSE의 경우 스레드의 삭제
if(bAutoDel==false)
{
GetExitCodeThread(_pWinThread->m_hThread, &dwExit);
_DbgStr(_T("WaitThreadEnd(W)-쓰레드 클래스 삭제(code=%d)", dwExit));
//if( _bClose) CloseHandle( _hThread );//하면 안됨클래스 해제시 자동 해제 된다.
delete _pWinThread;
}
_DbgStr(_T("WaitThreadEnd(W)-끝-%s-%X-%d"),_sMsg, _hThread, GetTickCount() );
return 1;
}
//===================================================================