2011-12-29 110 views
1

在我的主对话框中,我有一个函数可以创建一个进程并等待它完成。这可能需要15-20秒。如果我简单地等待使用WaitForSingleObject,我的对话变得无法响应。内部消息循环

我想使用EnableWindow(FALSE)和一个内部消息循环的组合来制作我的对话框块,但看起来没有像应用程序冻结一样,MessageBox和DoModal的做法。但我不确定如何做到这一点内部消息循环。

回答

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); 

等待进程退出,你可以用很短(< 30毫秒)的超时WaitForSingleObject调用消息循环。或MsgWaitForMultipleObjects。或GetExitCodeProcess

我想推荐另一种方法。
1)显示新模式弹出
2)开始在OnInitDialog处理程序的过程,并启动一个定时器
3)检查过程仍在的OnTimer处理程序运行,通过GetExitCodeProcess
4)调用的EndDialog时,这个过程是不更长的运行

3

恐怕你的做法不行。你的应用程序是单线程的,或者至少你的UI是。在您调用WaitForSingleObject之后,您的线程将进入休眠状态,并且不会处理Windows消息。你有一个内部消息循环的事实并不重要。您可能应该启动一个新线程并使用它来等待进程完成,然后通知您的UI线程并退出。或类似的规定。

1

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

1

,你可以:

  • (有点复杂)使用MsgWaitForMultipleObjects(或MsgWaitForMultipleObjectsEx)等待进程结束的消息arr中ive(以正常方式处理它)。
  • (简单)使用RegisterWaitForSingleObject注册一个在进程退出时在单独的线程中调用的回调函数(也许该回调函数只是将消息发布到窗口中)。
  • (很简单)创建自己的线程来执行在等待。

我会用第二个选项去。

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); 
    }