2014-01-14 6 views
4

방금 ​​MFC를 배우기 시작했으며 멀티 스레딩에 대한 이해를 돕기 위해 하나의 대화 상자 기반 응용 프로그램을 작성했습니다.부모 스레드에서 작업자 스레드 종료 - MFC

기본 대화 상자에는 진행률 표시 줄, 시작 단추 및 취소 단추가 있습니다.

시작 버튼을 클릭하면 API 호출을 통해 일부 처리를 수행 할 작업자 스레드를 만들고 주 스레드가 진행률 막대를 처리합니다.

내가 진행 표시 줄 상태 아래

WM_UPDATE_CONTROL 
WM_STOP_CONTROL 

를 업데이트하고 중지하려면 Windows 메시지의 몇 가지를 정의한 내가 만든 코드는 지금까지 내가 종료 할

HWND* phObjectHandle; 
CWinThread* thread; 

void CprogCtrlDlg::OnBnClickedStart() { 
    phObjectHandle = new HWND; // Set object handle for Worker thread 
    *phObjectHandle = GetSafeHwnd(); 

    // create worker thread 
    if(NULL == (thread = AfxBeginThread(ThreadFunc, phObjectHandle))) { 
     EndDialog(IDCANCEL); 
    } 

    AfxMessageBox(L"Thread started"); 
    // Set Progress bar to marquee 
} 

void CprogCtrlDlg::OnBnClickedCancel() { 
    // kill the Worker thread 
} 

UINT CprogCtrlDlg::ThreadFunc(LPVOID pParam) { 
    HWND *pObjectHandle = static_cast<HWND *>(pParam); 
    CprogCtrlImpDlg* threadDlg = (CprogCtrlImpDlg*) pParam; 

    return threadDlg->ThreadFuncRun(pObjectHandle); 
} 

UINT CprogCtrlDlg::ThreadFuncRun(HWND* pObjectHandle) { 

    ::PostMessage(*pObjectHandle, WM_UPDATE_CONTROL, 0, 0); 

    // repetitive API CALL in a loop 

    ::PostMessage(*pObjectHandle, WM_STOP_CONTROL, 0, 0); 
    AfxMessageBox(L"Thread completed"); 

    return 0; 
} 

취소 버튼을 클릭하면 부모 스레드의 작업자 스레드입니다.

TerminateThread()를 사용해 보았지만 (권장되지는 않았지만) 스레드를 죽일 수는 없었습니다.

부모 스레드에서 작업자 스레드 종료에 대한 의견을 말하고 공유하십시오.

나는이 같은 코드 뭔가를 개정 할 윈도우 7

TIA

+1

그냥 빨리 점 : 간단한 진행률 표시 줄 업데이트

, 당신은 내부에 이런 일을 작업 루프를 이벤트 체크 를 넣을 수 있습니다. –

+0

@ 로거 예 (사용하는 것은 나쁜 생각입니다.) !!! 방금 문제를 해결할 수 있는지 확인하려고했습니다. – MajorBetaVictory

+0

또한 'delete pObjectHandle'을 수행 할 필요가 없으므로 충돌이 발생할 수 있습니다. 또한 당신은'lParam'을 두 가지 다른 타입으로 캐스팅합니다. 쓰레드 간의 올바른 통신 방법은 이벤트입니다. 이렇게 많은 예가 있습니다. 두려워 거기에 현재 코드 문제가 많이 있습니다 :-( –

답변

5

에서 Visual Studio 2010을 사용하고 있습니다.

은 (생성자에 NULL로 초기화) 스레드 핸들 및 이벤트 핸들을 보유하는 대화 상자 클래스의 일부 멤버 변수 유무 :

CWinThread* m_hThread; 
HANDLE m_hKillEvent; 

를 사용하여 정적 기능을 스레드의 진입 점으로, 대화 상자를 전달합니다 당신이 스레드를 시작하면

UINT ThreadFunc(LPVOID pParam) 
{ 
    // static thread func - delegate to instance 
    CprogCtrlDlg* pDlg = static_cast<CprogCtrlDlg*>(pParam); 
    return pDlg->ThreadFuncRun(); 
} 

가 너무 이벤트를 만들 : 당신이 대화 상자의 모든 변수에 액세스 할 수 있도록 매개 변수로, 다음 클래스 인스턴스로 다시 전화를 위임 this

을 당신이 게시 할 수

void CprogCtrlDlg::OnBnClickedCancel() 
{ 
    // kill the Worker thread 
    SetEvent(m_hKillEvent); 

    // wait for it to die 
    DWORD dwRet = WaitForSingleObject(m_hThread->m_hThread, 5000); 
    if (dwRet == WAIT_TIMEOUT) 
    { 
     // thread failed to die after 5 seconds 
     // error handling (maybe TerminateThread here) 
    } 
} 

(지금 대화 클래스) 스레드 함수에서 :

void CprogCtrlDlg::OnBnClickedStart() 
{ 
    // create worker thread 
    m_hKillEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 
    m_hThread = AfxBeginThread(ThreadFunc, this); 
    AfxMessageBox(L"Thread started"); 
} 

17,451,515,는 이벤트를 설정, 스레드를 죽이고 죽음에 신호를 얻을 것이다 스레드 핸들을 기다립니다 자신에게 메시지 진행 상황을 표시하고 킬 (kill) 요청 잡으려고 이벤트에서 대기를 사용 : 나는, 포인터의 정리를 초기화를 남겨 등을 처리 한

UINT CprogCtrlDlg::ThreadFuncRun() 
{ 
    // instance thread func 
    PostMessage(WM_UPDATE_CONTROL, 0, 0); 

    // main loop 
    while (true) 
    { 
     // check kill 
     DWORD dwRet = WaitForSingleObject(m_hKillEvent, 0); 
     if (dwRet == WAIT_OBJECT_0) break; 

     // do a little work here and update progress 
     // ... so this is part of your working loop ... 
     PostMessage(WM_UPDATE_CONTROL, 0, 1 /*2,3,4,...*/); 
    } 

    // normal thread exit 
    PostMessage(WM_STOP_CONTROL, 0, 0); 
    return 0; 
} 

을하지만 당신은 내가 희망 일반적인 아이디어를 얻을.

스레드 루프를 코딩 할 수있는 몇 가지 방법이 있습니다. 위와 같이 이벤트가 신호되는지 정기적으로 확인하거나 이벤트가 신호를 받아 작업을 수행 할 수 있습니다. 둘 다 공통된 패턴이며 두 작업 (트리거 작업 및 다른 작업)과 함께 자주 사용됩니다. 여러 이벤트를 기다리는 경우주의해야 할 중요한 사항은 this answer을 참조하십시오.* 지금 *`TerminateThread`를 사용하지 마십시오,

UINT CprogCtrlDlg::ThreadFuncRun() 
{ 
    // instance thread func 
    PostMessage(WM_UPDATE_CONTROL, 0, 0); 

    // main loop 
    for (int i = 0; i < 100; ++i) 
    { 
     // check kill 
     DWORD dwRet = WaitForSingleObject(m_hKillEvent, 0); 
     if (dwRet == WAIT_OBJECT_0) break; 

     // do a little work here and update progress 
     PostMessage(WM_UPDATE_CONTROL, 0, (LPARAM)i); 
    } 

    // normal thread exit 
    PostMessage(WM_STOP_CONTROL, 0, 0); 
    return 0; 
} 
+1

고마워요 로저! – MajorBetaVictory

관련 문제