mfc_Thread_2 - 8BitsCoding/RobotMentor GitHub Wiki

Thread๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ ๋งŒ๋“ค์–ด์„œ ํ˜‘๋ ฅํ•˜๋ฉฐ ์“ฐ๋Š” ๋ฒ•์— ๋Œ€ํ•ด ๊ณ ๋ฏผ

์šฐ์„  ์†Œ์ˆ˜๋ฅผ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ•˜๋‚˜ ์ƒ์„ฑํ•ด๋ณธ๋‹ค.

int IsPrime(int a_num)
{
    int i;
    for(i = 2; i < a_num; i++)
    {
        if(a_num % i == 0) return 0;
    }
    return 1;
}

2~200000 ์‚ฌ์ด์˜ ์†Œ์ˆ˜๋ฅผ ๋ชจ๋‘ ํ•ฉ์‚ฐํ•˜๋Š” Thread๋ฅผ ์ƒ์„ฑํ•ด ๋ณด์ž.

DWORD WINAPI InsertItemToList(void * ap_data)
{
    ThreadData * p_data = (ThreadData *)ap_data;
    CString str;
    int index;
    __int64 sum = 0;

    int start_tick = GetTickCount();

    for(unsigned int i = 2; i < 200000; i++) {
        if(WaitForSingleObject(p_data->h_kill_event,0) == WAIT_OBJECT_0) break;

        if(IsPrime(i)) sum += i;

        if(!(i%100000)) {
            str.Format(L"์ž‘์—… ์ง„ํ–‰์ค‘ %d๊นŒ์ง€ ์ฒดํฌํ•จ!");
            index = p_data->p_list_box->InsertString(-1, str);
            p_data->p_list_box_SetCurSel(index);
        }
    }

    str.Format(L"2~200000๊นŒ์ง€ ์†Œ์ˆ˜์˜ ํ•ฉ์€ %lld์ด๋‹ค. (%dms)", sum, GetTickCount() - start_tick);
    index = p_data->p_list_box->InsertString(-1, str);
    p_data->p_list_box_SetCurSel(index);

    CloseHandle(p_data->h_thread);
    p_data->h_thread = NULL;

    return 0;
}

๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ๋•Œ๋งˆ๋‹ค Thread๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋ณ€๊ฒฝํ•ด๋ณด์ž.

์ด๋ฏธ์ง€

// Dlg.h
struct ThreadData
{
    HWND h_wnd;         // ๋Œ€ํ™”์ƒ์ž์˜ Handle
    unsigned int step;  // 
    CListBox * p_list_box;
    HANDLE h_kill_event;
    HANDLE h_thread;
    DWORD thread_id;
};
// Dlg.cpp
private:
    unsigned int m_step = 200000;
// Thread ์ƒ์„ฑ ๋ฒ„ํŠผ
ThreadData * p = new ThreadData;
p->h_wnd = m_hWnd;
p->step = m_stop;
p->p_list_box = &m_data_list;
p->h_kill_event = CreateEvent(NULL, 1, 0, NULL);
p->h_thread = CreateThread(NULL, 0, InsertItemToList, p, 0, &p->thread_id);

CString str;
str.Format(L"%08x : %u ๊นŒ์ง€ ํ•ฉ์‚ฐ", p->thread_id, p->step);
int index = m_thread_list.InsertString(-1, str);
m_thread_list.SetItemDataPtr(index, p);

m_step *= m_step;
DWORD WINAPI InsertItemToList(void * ap_data)
{
    ThreadData * p_data = (ThreadData *)ap_data;
    CString str;
    int index;

    str.Format(L"[%08x] ์ž‘์—…์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค!", p_data->thread_id);
    p_data->p_list_box->SetCurSel(index);
    __int64 sum = 0, kill_flag = 0;
    int start_tick = GetTickCount();
    unsigned int i;

    for(i = 2; i < 200000; i++) {
        if(WaitForSingleObject(p_data->h_kill_event,0) == WAIT_OBJECT_0) {
            str.Format(L"[%08x] ์ž‘์—… ์ค‘๋‹จ ์ฒดํฌํ•จ!", p_data->thread_id);
            index = p_data->p_list_box->InsertString(-1, str);
            kill_flag = 1;
            break;
        }

        if(IsPrime(i)) sum += i;

        if(!(i%100000)) {
            str.Format(L"[%08x] ์ž‘์—… ์ง„ํ–‰์ค‘ %d๊นŒ์ง€ ์ฒดํฌํ•จ!", p_data->thread_id);
            index = p_data->p_list_box->InsertString(-1, str);
            p_data->p_list_box_SetCurSel(index);
        }
    }

    str.Format(L"[%08x] 2~%u๊นŒ์ง€ ์†Œ์ˆ˜์˜ ํ•ฉ์€ %lld์ด๋‹ค. (%dms)", p_data->thread_id, i, sum, GetTickCount() - start_tick);
    index = p_data->p_list_box->InsertString(-1, str);
    p_data->p_list_box_SetCurSel(index);

    str.Format(L"[%08x] ์ž‘์—…์„ ์ค‘๋‹จํ•ฉ๋‹ˆ๋‹ค!", p_data->thread_id);
    p_data->p_list_box->SetCurSel(index);

    CloseHandle(p_data->h_thread);
    
    if(WaitForSingleObject(p_data->h_kill_event, 0) == WAIT_OBJECT_0) kill_flag= 1;
    ::PostMessage(p_data->h_wnd, 27001, kill_flag, (LPARAM)p_data);

    return 0;
}

์ฝ”๋“œ์„ค๋ช…

(์ฐธ๊ณ ) LPARAM, WPARAM

LPARAM : ์ •ํ†ต์ ์œผ๋กœ 4 bytes ์ฃผ์†Œ๊ฐ’์„ ๋ณดํ†ต ๋„˜๊ฒจ์ค€๋‹ค.

WPARAM : ์ตœ๊ทผ์—๋Š” 4 bytes ๊ฐ€ ๋˜์—ˆ์œผ๋‚˜ ์˜ˆ์ „์— 2 bytes๋กœ ๋ณดํ†ต ์ฃผ์†Œ๊ฐ’์„ ๋„ฃ์ง€ ์•Š๊ณ  char, byte๋“ฑ์„ ๋„ฃ์—ˆ์Œ.

::PostMessage(p_data->h_wnd, 27001, kill_flag, (LPARAM)p_data); : ๋ถ€๋ชจ ๋‹ค์ด์–ผ๋กœ๊ทธ(p_data->h_wnd)๋กœ ๋ฉ”์‹œ์ง€(27001)๋ฅผ ๋ณด๋‚ธ๋‹ค. ๋ฉ”์‹œ์ง€์˜ WPARAM = kill_flag(์šด์šฉ์ž๊ฐ€ ์ฃฝ์ธ๊ฒƒ์ธ์ง€ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ฃฝ์€๊ฒƒ์ธ์ง€), LPARAM = p_data์˜ ์ฃผ์†Œ๊ฐ’.

if(WaitForSingleObject(p_data->h_kill_event, 0) == WAIT_OBJECT_0) kill_flag= 1; : ๋งˆ์ง€๋ง‰์— ์ด ํ•œ ์ค„์ด ๋” ๋“ค์–ด๊ฐ€๋Š” ์ด์œ ๋Š”?? -> 200000๋ฒˆ๊นŒ์ง€ ๋„๋Š”๋ฐ 199999๊นŒ์ง€ ๋„๋Š” ์ˆœ๊ฐ„์— ์šด์šฉ์ž๊ฐ€ Thread์ข…๋ฃŒ๋ฅผ ๋ˆ„๋ฅด๋ฉด kill_flag๊ฐ€ 0์ธ์ฑ„๋กœ ๋๋‚˜๋ฒ„๋ฆฐ๋‹ค. ๊ทธ ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ.

// thread ์„ ํƒ ์ข…๋ฃŒ
int index = m_thread_list.GetCurSel();
if(LB_ERR != index)
{
    ThreadData* p = (ThreadData*)m_thread_list.GetItemDataPtr(index);
    if(p->h_thread != NULL) {
        SetEvent(p->h_kill_event);
        MSG msg;
        while(p->h_thread != NULL) {
            if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }
    delete p;
}
}
else {

}

์ฝ”๋“œ์„ค๋ช…

PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) : ๋ฉ”์‹œ์ง€๊ฐ€ ์žˆ์œผ๋ฉด ๋™์ž‘ ์—†์œผ๋ฉด ๊ทธ๋ƒฅ ๋„˜์–ด๊ฐ, RM_REMOVE : ๋ฉ”์‹œ์ง€๋ฅผ ๋ณต์‚ฌํ•˜์ง€ ์•Š๊ณ  ๊บผ๋‚ด์˜ด

๊ธฐ์กด GetMessage()์™€์˜ ์ฐจ์ด์ ์€ ๋ฉ”์‹œ์ง€๊ฐ€ ์žˆ๋Š”์ง€ ์—†๋Š”์ง€ ํ™•์ธํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

GetMessage๋ฅผ ์“ฐ๋ฉด ๋ฉ”์‹œ์ง€๋ฅผ ๋ฌดํ•œ์ • ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ๋ฐ๋“œ๋ฝ์— ๊ฑธ๋ฆด ์ˆ˜ ์žˆ๋‹ค.

์‚ฌ์šฉ์ž ์ง€์ • ๋ฉ”์‹œ์ง€(27001) ์ถ”๊ฐ€

ํด๋ž˜์Šค ๋งˆ๋ฒ•์‚ฌ(Shift+Ctrl+x) -> ์‚ฌ์šฉ์ž ์ง€์ • ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€ -> 27001

// On27001
ThreadData * p = (ThreadData *)lParam;
int count = m_thread_list.GetCount();
for(int i = 0; i < count; i++) {
    if(m_thread_list.GetItemDataPtr(i) == p) {
        m_thread_list.DeleteString(i);
        CloseHandle(p->h_kill_event);

        if(wParam == 0) delete p;
        else p->thread = NULL;

        break;
    }
}
// OnDestroy()
OnBtnAllStop();
// ๋ชจ๋“  Thread ์ข…๋ฃŒ ๋ฒ„ํŠผ (OnBtnAllStop())
ThreadData * p;
int count = m_thread_list.GetCount();
for(int i = 0; i < count; i++){
    p = (ThreadData*) m_thread_list.GetItemDataPtr(i);
    SetEvent(p->h_kill_event);
}

CString str;
str.Format(L"Thread %d๊ฐœ๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.", count);
int index = m_data_list.InsertString(-1, str);
m_data_list.SetCurSel(index);

MSG msg;
while(count) {
    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
        if(msg.message == 27001) {
            count--;
            msg.wParam = 0;     // kill_flag๋ฅผ 1๋กœ ๋ฐ”๊พธ๋ฉด ์—ฌ๊ธฐ์„œ delete๋ฅผ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

index = m_data_list.InsertString(-1, L"๋ชจ๋“  Thread๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.!");
m_data_list.SetCurSel(index);