2009-10-29 57 views
2

每个人都可能知道的代码运行程序,等待它结束:由我自己的CreateProcess与WaitForSingleObject的性能下降

CreateProcess(... 
    WaitForSingleObject(Process.hProcess, INFINITE 

它被多次使用。但是最近我发现,当它启动一个带有多媒体播放的程序时,这个调用的性能比从一般文件管理器(Windows XP)执行的同样的过程要糟糕得多。这对我的(父母)进程的CPU消耗没有问题,但在播放片段时会出现意想不到的小停顿。

我做了一点变化是这样的:

CreateProcess ... 
do { 
    Sleep(100); 
    Res = WaitForSingleObject(Process.hProcess, 10); 
} while (Res == WAIT_TIMEOUT); 

它帮助。现在子进程没有问题地播放片段。 那么第一个片段出现了什么问题,并且在某处记录了它?正如我从测试中看到的,第二个“等待”比第一个更“放松”,但第一个至少没有正式吃掉CPU

回答

3

如果此代码在UI线程上运行, (直接或间接)将消息发送到窗口的其他进程的性能问题,因为您在等待子进程时不运行消息循环。 Sleep()WaitForSingleObject()都不会处理消息。

Windows资源管理器(文件管理器)不会受到这个问题,因为它:

  1. 不保持开放的句柄进程会启动在用户的请求(我认为这是比较容易的,因为浏览器的需求既不知道该进程何时退出或退出代码)或
  2. 不等待任何打开的进程句柄,它可能与子进程保持关联,重要的是
  3. 始终确保在等待句柄时运行消息循环。这在任何使用COM的进程中都非常重要,因为这个进程使用了​​大量的资源管理器。

而不是调用WaitForSingleObject(),您可以拨打MsgWaitForMultipleObjects()。如果您为dwWaitMask参数指定了QS_ALLINPUT,则当您的事件发出信号或者在线程的消息队列中输入时,MsgWaitForMultipleObjects将会返回。如果由于消息可用而返回MsgWaitForMultipleObjects(),您可以处理它并继续等待:

MSG msg; 
DWORD reason = WAIT_TIMEOUT; 
while (WAIT_OBJECT_0 != reason) { 
    reason = MsgWaitForMultipleObjects(1, &hChildProcess, FALSE, INFINITE, QS_ALLINPUT); 
    switch (reason) { 
    case WAIT_OBJECT_0: 
     // Your child process is finished. 
     break; 
    case (WAIT_OBJECT_0 + 1): 
     // A message is available in the message queue. 
     if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { 
      TranslateMessage(&msg); 
      DispatchMessage(&msg); 
      // Note that if your main message loop does additional processing 
      // (such as calling IsDialogMessage() for modeless dialogs) 
      // you will want to do those things here, too. 
     } 
     break; 
    } 
} 
+0

您正在观察错误的一面。显然,如果父母被阻止等待,子进程的性能会更差。 WTF的确如此。 – MSalters

+1

这个答案中的小bug:MsgWaitForMultipleObjects()指向的链接实际上指向Sleep()函数的MSDN文档。有点有趣的方式。 ;-) –