Multithreading and MFC
I am writing a multithreaded app. On the main thread is the main window which is a modeless dialog box. When the user clicks on the start button, it will create a new thread that does some stuff for a long time. On the main thread it will create a new modeless dialog box to display the status of that new thread, 1 per thread. I created kind of a template dialog box using the resource editor and I set a static text for the status to have an id of IDC_STATIC_NUMCYCLE. I poll the status of the threads during the OnIdle function. The updating of the status works with 1 thread only, but if I spawn more the static text for all will not update until the very end or if it is the only thread left running.
Declaration:
map<CSimDlg *, CSimulator *> simulations;
My OnIdle function:
BOOL CFGSim1App::OnIdle(LONG lCount)
{
CWinApp::OnIdle(lCount);
DWORD exitCode;
CString numOfCycle;
for (map<CSimDlg *, CSimulator *>::iterator iter = simulations.begin(); iter != simulations.end();)
{
// skip already finished threads
if (iter->second == NULL)
{
iter++;
continue;
}
if (GetExitCodeThread(iter->second->m_hThread, &exitCode))
{
if (exitCode == 0)
{
delete iter->second;
iter->second = NULL;
if (IsWindow(iter->first->m_hWnd))
{
iter->first->SetDlgItemText(IDC_STATIC_SIMSTATUS, L"Simulation done");
}
else
{
iter = simulations.erase(iter);
}
}
else
{
ULONG64 temp = iter->second->m_ul64NumOfCycle;
if (temp % 10000 == 0)
{
numOfCycle.Format(_T("%d"), temp);
iter->first->SetDlgItemText(IDC_STATIC_NUMCYCLE, numOfCycle);
}
iter++;
}
}
else
{
iter++;
}
}
return TRUE;
}
I am guessing the problem is with the id of the static text. Is there a way to work around this? Or do I need to declare a different id for each dialog box? Or is the problem elsewhere?
The (temp % 10000 == 0) condition is suspicious to me. You are assuming that temp will increment slowly enough that 10000 marks will be detected. This may not be the case. If you want to reduce GUI operations then introduce a "last count" variable for each thread, and update GUI only if temp is sufficiently larger than this variable, that is then set to temp.
BTW you don't need std::map
if all you do with the container is to traverse trough it, and don't use special features of the map. It might as well be a list of std::pair
, or list of some new structure. This new structure could hold the mentioned last count variable.
Your logic seems fine to me. Maybe MFC could require a repaint request after the text change:
iter->first->SetDlgItemText(IDC_STATIC_NUMCYCLE, numOfCycle);
iter->first->Invalidate();
I'm sorry but currently I don't have MFC handy to test...
链接地址: http://www.djcxy.com/p/39236.html上一篇: 在MFC / OpenCV项目的新窗口中进行额外的初始化
下一篇: 多线程和MFC