DoModal在关键部分

时间:2015-03-26 16:39:39

标签: multithreading process mfc openmp


在并行循环中,有一个关键部分。我尝试在关键部分中使用DoModal执行mfc对话框,但是由于主线程等待并行线程,因此我的对话框无法显示和执行。为了打破这种依赖,我创建了一个可执行文件,并将其作为并行循环中的一个进程运行。当进程显示对话框并获取信息时。它返回,其他线程继续运行。

然而,我的团队负责人坚持认为有一种更好的方法可以做到这一点,经过几个小时的搜索我无法弄清楚:\\

我并行尝试了一个单独的线程。它没有用。
我试过CWinThread(谷歌说它是gui线程:\没有帮助) 我累了创建一个exe并运行它。这有效:)

int someCriticDialog()
{
  #pragma omp critic (showCriticDlg)
  {
   CMyDialog ccc;
   ccc.DoModal();
   /* However the code below works
      CreateProcess("someCriticDlg.exe", null, &hProcess);
      WaitForSingeObject(hProcess, INFINITE);
   */
  }
}

#pragma omp parallel
for (int i = 0; i < 5; i++)
  someCriticDialog();

1 个答案:

答案 0 :(得分:1)

让我们说这是问题所在:

void trouble_maker() 
{
    Sleep(10000);//application stops for 10 seconds
}

您可以使用PostMessage + PeekMessage +模式对话框等待它通过GUI窗口完成:

void PumpWaitingMessages()
{
    MSG msg;
    while (::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
        if (!AfxGetThread()->PumpMessage())
            return;
}

BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
    ON_COMMAND(2000, OnDoSomething)
    ON_COMMAND(IDCANCEL, OnCancel)
END_MESSAGE_MAP()

CMyDialog::CMyDialog(CWnd* par /*=NULL*/) : CDialog(IDD_DIALOG1, par)
{
    working = false;
    stop = false;
}

BOOL CMyDialog::OnInitDialog()
{
    BOOL res = CDialog::OnInitDialog();

    //call the function "OnDoSomething", but don't call it directly
    PostMessage(WM_COMMAND, 2000, 0);

    return res;
}

void CMyDialog::OnCancel()
{
    if (working)
    {
        stop = true;
    }
    else
    {
        CDialog::OnCancel();
    }
}

void CMyDialog::OnDoSomething()
{
    HANDLE h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&trouble_maker, NULL, 0, NULL);
    working = true;
    for (;;)
    {
        if (WAIT_TIMEOUT != WaitForSingleObject(h, 100)) break;
        PumpWaitingMessages();
        //update progress bar or something...

        if (stop)
        {
            //terminate if it's safe
            //BOOL res = TerminateThread(h, 0);
            //CloseHandle(h);
            //CDialog::OnCancel();
            //return;
        }
    }

    working = false;
    MessageBox("done");
}