2009-10-29 59 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文檔。有點有趣的方式。 ;-) –