mfc_Thread - 8BitsCoding/RobotMentor GitHub Wiki
(์ฃผ์)
MFC์์ GetDlgItem๊ณผ ๊ฐ์ Temporary ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ํจ์๋ ์ฌ์ฉํ๋ฉด ์๋๋ค.
Thread๊ฐ ๋์ํ๋ ๋์ Main Thread์์๋ ์์๊ฐ์ฒด(GetDlgItem์์ ๋ฐํ๋ ๊ฐ์ฒด)์ ๋ฉ๋ชจ๋ฆฌ๋ ๋ชจ๋ ์ง์ฐ๊ธฐ ๋๋ฌธ!
Thread๊ฐ ํ์ํ Example
ํ๋์ ๋ฒํผ์ ๋๋ฅด๋ฉด ์๋์ ๊ฐ์ ์์ ์ ํ๋ค๊ณ ๊ฐ์ ํด๋ณด์.
// Button Click
CString str;
int index;
for(int i = 0; i < 10000; i++)
{
str.Format(L"item %05d", i);
index = m_data_listbox.InsertString(-1, str);
m_data_listbox.SetCurSel(index);
}
์ for๋ฌธ์ด ๋ชจ๋ ๋์ํ๊ธฐ ์ ๋ฉ์ธ ๋ค์ด์ผ๋ก๊ทธ๋ฅผ ์์ง์ด๊ฑฐ๋ ์ถ๊ฐ ํด๋ฆญ์ด ๋ถ๊ฐ๋ฅํ๋ค.
Thread๋ฅผ ํตํ์ฌ ๊ฐ์ ํด ๋ณด์.
Thread ์์ฑ
DWORD WINAPI InsertItemToList(void* ap_data)
{
CString str;
int index;
for(int i = 0; i < 10000; i++)
{
str.Format(L"item %05d", i);
index = ap_data->InsertString(-1, str);
ap_data->SetCurSel(index);
}
return 0;
}
HANDLE h_thread;
h_thread = CreateThread(NULL, 0, InsertItemToList, &m_data_listbox, 0, NULL);
if(h_thread != NULL) {
// Thread ์์ฑ
}
CreateThread์ ๋ํ ์ค๋ช
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
__drv_aliasesMem LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
- lpThreadAttributes : ์ฌ์ฉ์ ๊ณ์ ์ปจํธ๋กค, ๊ด๋ฆฌ์๋ชจ๋, ์ผ๋ฐ์ฌ์ฉ์ ๋ชจ๋ ๋ฑ
- dwStackSize : ๊ฐ Thread์ Stack Size, 0์ผ๋ก ๋๋ฉด 1MB (๋ณดํต 1MB์) 32bit ์ด์์ฒด์ ๊ธฐ์ค์ผ๋ก ์ต๋ ์ฌ์ฉ๊ฐ๋ฅ ๋ฉ๋ชจ๋ฆฌ๊ฐ 4GB์ด๊ณ 2GB๋ OS์์ ์ฌ์ฉํ๊ธฐ์ 2GB ์ค 1700MB ์ ๋๋ง ์ฌ์ฉ์ด ๊ฐ๋ฅ ๋ฐ๋ผ์ StackSize๋ฅผ 1MB๋ก ๋๋ฉด Thread 1700๊ฐ ์ ๋์ฌ์ฉ์ด ๊ฐ๋ฅ
- lpStartAddress : ThreadFunc ์ฃผ์
- lpParameter : Thread์ ๋๊ธธ ์ธ์
- dwCreationFlags : Thread ์์ฑ ์ Flag ์ง์
- lpThreadId : ๋ฐํ๋๋ Thread ID
์ ๋ง ์ฝ๋ค?? ๋ญ๊ฐ ๋ฌธ์ ์ง???
- Main Thread๊ฐ ์ข ๋ฃ๋๋ค๊ณ ๋ด๋ถ Thread๊ฐ ๋ชจ๋ ์ข ๋ฃ๋๋๊ฒ์ด ์๋๋ค!
For๋ฌธ์ด ๋ชจ๋ ๋์๊ฐ๊ธฐ ์ MainWindow๋ฅผ ์ฃฝ์ด๋ฉด?? -> Thread๋ ๊ทธ๋๋ก ์ด์์๋๋ค.
// Dlg.h
HANDLE mh_thread = NULL;
mh_thread = CreateThread(NULL, 0, InsertItemToList, &m_data_listbox, 0, NULL);
if(mh_thread != NULL) {
// Thread ์์ฑ
}
ํด๋์ค ๋ง๋ฒ์ฌ -> WM_DESTROY ์์ฑ
// OnDestroy()
CDialogEx::OnDestroy();
if(mh_thread != NULL)
{
TerminateThread(mh_thread, 0);
}
์ ์ฒ๋ผ ํ๋ฉด ๋ ๊น??
๋ฌธ์ ๋ Thread ๋ด๋ถ์์ ๋์ ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์ํ์ง ์๊ณ ๋น์ ์ ์ข ๋ฃ๋ฅผ ํด๋ฒ๋ฆฌ๊ฒ ๋๋ค.
์ด๋ฐ ๋น์ ์ ์ข ๋ฃ์ ๊ฐ์ฅ ํฐ ๋ฌธ์ ์ ์ Mutex์์ญ์ ์ค์ ํ๋ฉด ๋น์ ์ ์ข ๋ฃ๋ Mutex์ ์ํด์ lock์ด ๋ฐ์ํ ์ ์๋ค๋ ์ ์ด๋ค.
์ ๋ง ๊ธํ๊ฒ ์ผ์ ์ฒ๋ฆฌํด์ผํ ๋
TerminateThread
๋ฅผ ์ฐ์...
๊ทธ๋ผ ์ด์ฉ๋ผ๊ณ ?
EVENT๋ฅผ ์ด์ฉํด๋ณด์.
// Dlg.h
struct ThreadData
{
CListBox* p_list_box;
HANDLE h_kill_event;
HANDLE h_thread;
};
private:
ThreadData m_thread_data;
// OnInitDialog
m_thread_data.p_list_box = &m_data_list;
m_thread_data.h_kill_event = CreateEvent(NULL, 1, 0, L"Tips001");
m_thread_data.h_thread = NULL;
์ฝ๋์ค๋ช (CreateEvent)
HANDLE CreateEventA(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCSTR lpName
);
- lpEventAttributes : ์ฌ์ฉ์ ๊ณ์ ์ปจํธ๋กค, ๊ด๋ฆฌ์๋ชจ๋, ์ผ๋ฐ์ฌ์ฉ์ ๋ชจ๋ ๋ฑ
- bManualReset : 1(ManualReset)๋ก ๋๋ฉด ๋ด๊ฐ SetEventํ๋ฉด Set ์ค์ / 0์ผ๋ก ๋๋ฉด ์ผ์ ์๊ฐ์ด ์ง๋๋ฉด CloseEvent
- bInitialState : ์ฒ์์ 0์ผ๋ก ์์ํ ์ง 1๋ก ์์ํ ์ง, 0์ผ๋ก ๋๋ฉด 0์ผ๋ก ์์
- lpName : ์ด๋ฒคํธ๊ฐ์ฒด ์ด๋ฆ, ์ด๋ฒคํธ ์ด๋ฆ์ ์๋ฉด OpenEvent()๋ฅผ ํตํด์ ์ด๋ฒคํธ๋ฅผ ๊ณต์ ํ ์ ์๋ค.
m_thread_data.h_thread = CreateThread(NULL, 0, InsertItemToList, &m_thread_data, 0, NULL);
if(m_thread_data.h_thread != NULL) {
// Thread ์์ฑ
}
DWORD WINAPI InsertItemToList(void* ap_data)
{
ThreadData * p_data = (ThreadData *)ap_data;
CString str;
int index;
for(int i = 0; i < 10000; i++)
{
if(WaitForSingleObject(p_data->h_kill_event, 1) == WAIT_OBJECT_0)
{
// Event๊ฐ Set ์ํ์ด๋ฉด == WAIT_OBJECT_0
// Event๊ฐ Set ์ํ๊ฐ ์๋๋ฉด == WAIT_TIMEOUT
break;
}
str.Format(L"item %05d", i);
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;
}
// OnDestroy()
CDialogEx::OnDestroy();
if(m_thread_data.h_thread != NULL)
{
SetEvent(m_thread_data.h_kill_event);
while(m_thread_data.h_thread != NULL);
}
์ด๋ ๊ฒ ํ๋ฉด ๋ ๋ค๋ฅธ ๋ฌธ์ ์ ์ด ๋ฐ์
while(m_thread_data.h_thread != NULL);
์์๋ Thread๊ฐ ์ฃฝ๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ ์๊ณThread์
index = p_data->p_list_box->InsertString(-1, str);
๋ Main Thread์์ ๋ฉ์์ง ์ฒ๋ฆฌํ ์๋ต์ ์ฃผ๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉด์ ๋ฐ๋๋ฝ ์ํ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค.
ํด๊ฒฐ๋ฐฉ์??
// OnDestroy()
CDialogEx::OnDestroy();
if(m_thread_data.h_thread != NULL)
{
SetEvent(m_thread_data.h_kill_event);
MSG msg;
while(m_thread_data.h_thread != NULL && GetMessage(&msg, NULL, 0, 0)) {
TranslateMessge(&msg);
DispatchMessage(&msg);
}
}
๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ๋ ๊ตฌ๋ฌธ์ ๋ฃ์ด์ค๋ค.
ํ์ง๋ง ์ด๋ฒ ์์ ์ ์น๋ช ์ ๋ฌธ์ ์ ์ด ์์.
Thread์์
p_data->p_list_box->InsertString(-1, str);
๋ฉ์ธ Thread์ ๋์์ ์๊ตฌํ๊ฒ ๋๋๋ฐ,์ด๋ ๊ฒ ๋์ํ ๊ฒฝ์ฐ Thread๊ฐ ๋ช๊ฐ ์๋๋ฉด ์ ์์ ์ผ๋ก ๋์ํ๋
Thread์ ๊ฐ์๊ฐ ๋ง์ ์ง์๋ก Main Thread์ ๋ถํ๊ฐ ์ปค์ง๊ฒ ๋๋ค.
๋ค์๊ฐ์ข์์ ํด๊ฒฐ๋ฐฉ๋ฒ์ ๋ชจ์ํด๋ณธ๋ค.