内部消息循环

时间:2011-12-29 10:40:36

标签: c++ mfc

在我的主对话框中,我有一个创建进程并等待它完成的函数。可能需要15-20秒。如果我只是等待使用WaitForSingleObject,我的对话框就会没有响应。

我想使用EnableWindow(FALSE)和内部消息循环的组合来使我的对话框阻止,但看起来不像应用程序冻结,就像MessageBox和DoModal那样。但我不知道如何做一个内部消息循环。

5 个答案:

答案 0 :(得分:3)

我担心你的方法不起作用。您的应用是单线程的,或者至少是您的用户界面。在调用WaitForSingleObject之后,您的线程将进入休眠状态,并且它不会处理Windows消息。你有一个内部消息循环的事实并不重要。您可能应该启动一个新线程并使用它等待进程完成,然后通知您的UI线程并退出。或者沿着这些方向发展。

答案 1 :(得分:2)

运行内部消息循环是相当简单的编码。

如下所示:

EnableWindow(FALSE);
while ( /* check for my exit condition */ )
{
    MSG msg;
    if(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) 
    { 
        if( !AfxGetApp()->PumpMessage() ) 
        {
            ::PostQuitMessage(0); 
        }
    } 
}
EnableWindow(TRUE);

要等待进程退出,您可以在消息循环中使用非常短的(< 30ms)超时WaitForSingleObject调用。或MsgWaitForMultipleObjects。或GetExitCodeProcess

我想推荐另一种方法 1)显示新的模态弹出窗口
2)在OnInitDialog处理程序中启动进程并启动计时器
3)检查进程是否仍在OnTimer处理程序中运行,GetExitCodeProcess
4)当进程不再运行时调用EndDialog

答案 2 :(得分:1)

尝试MsgWaitForMultipleObjects函数;它可以在等待事件对象时处理Windows消息。

答案 3 :(得分:1)

你可以:

  • (有点复杂)使用MsgWaitForMultipleObjects(或MsgWaitForMultipleObjectsEx)等待进程完成以使消息到达(以正常方式处理它)。
  • (简单)使用RegisterWaitForSingleObject来注册在进程退出时在单独的线程中调用的回调(并且可能让回调只是将消息发布到您的窗口)。
  • (相当简单)创建自己的线程来进行等待。

我会选择第二个选项。

答案 4 :(得分:0)

    DWORD ec; 

    if(CreateProcess( NULL,   // No module name (use command line). 
        szExe,                    // Command line. 
        NULL,                                           // Process handle not inheritable. 
        NULL,                                           // Thread handle not inheritable. 
        FALSE,                                      // Set handle inheritance to FALSE. 
        procFlags,                // No creation flags. 
        NULL,                                           // Use parent's environment block. 
        NULL,                                           // Use parent's starting directory. 
        &si,                                            // Pointer to STARTUPINFO structure.
        &pi )                                           // Pointer to PROCESS_INFORMATION structure.
        ) 
 { 

   while(GetExitCodeProcess(pi.hProcess, &ec) && ec == STILL_ACTIVE) 
   { 
    MSG msg; 
    while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) 
    { 
     if(!AfxGetApp()->PumpMessage()) 
     { 
      ::PostQuitMessage(0); 
      break; 
     } 
    } 
    // let MFC do its idle processing 
    LONG lIdle = 0; 
    while(AfxGetApp()->OnIdle(lIdle++)) 
     ; 
     } 
  } 
  if(ec) 
  {
     CloseHandle(pi.hProcess);
  }