Вы не проверяете возвращаемое значение 2-го CreateProcess()
, чтобы увидеть, не сработало ли оно, но, что более важно, вы полностью неправильно используете MsgWaitForMultipleObjects()
:
вы не передаете оба процесса обрабатывают до MsgWaitForMultipleObjects()
, даже если вы устанавливаете для его параметра nCount
значение 2.
вы безоговорочно вызываете ProcessMessages()
, даже когда MsgWaitForMultipleObjects()
не сообщает вам, что сообщения ожидают обработки.
Предложение until
вашего цикла проверяет неправильное значение завершения, поэтому ваш цикл преждевременно прервется при ЛЮБОМ условии, которое нетайм-аут, например: когда либо завершается процесс, либо когда сообщение находится в очереди.
есть важное предостережение с установкой для параметра bWaitAll
значения True, что вам необходимознать об этом - см. MsgWaitForMultipleObjects - очень сложный API на MSDN для получения подробной информации об этом.
С учетом вышесказанного, попробуйте что-то более похожее на это:
var
...
arrHandles: array[0..1] of THandle;
numHandles, i: Integer;
begin
...
ccOk := CreateProcess(nil, PChar(ExecutableFirst + ' ' + CommandsFirst), @saSecurity, @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess);
if not ccOk then
RaiseLastOSError;
CloseHandle(piProcess.hThread);
arrHandles[0] := piProcess.hProcess;
numHandles := 1;
try
ccOk := CreateProcess(nil, PChar(ExecutableSecond + ' ' + CommandsSecond), @saSecurity, @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess);
if not ccOk then
RaiseLastOSError;
CloseHandle(piProcess.hThread);
arrHandles[1] := piProcess.hProcess;
numHandles := 2;
// there is a caveat when setting bWaitAll=True that the wait will not be
// completely satisfied until both handles are signaled AND the calling thread
// receives an input event! That last caveat is not desirable, so setting
// bWaitAll=False instead to avoid that so the loop can break immediately when
// both handles are signaled...
repeat
Running := MsgWaitForMultipleObjects(numHandles, arrHandles, False, INFINTE, QS_ALLINPUT);
if {(Running >= WAIT_OBJECT_0) and} (Running < (WAIT_OBJECT_0 + DWORD(numHandles))) then
begin
i := Integer(Running - WAIT_OBJECT_0);
CloseHandle(arrHandles[i]);
if i = 0 then arrHandles[0] := arrHandles[1];
Dec(numHandles);
end
else if Running = (WAIT_OBJECT_0 + DWORD(numHandles)) then begin
Application.ProcessMessages;
end
else if Running = WAIT_FAILED then begin
RaiseLastOSError;
end;
until numHandles = 0;
except
for i := 0 to numHandles-1 do begin
TerminateProcess(arrHandles[i], 0);
CloseHandle(arrHandles[i]);
end;
raise;
end;
BidsConversion; //run this when both processes have finished without error
...
end;
Как говорится,рассмотрите возможность асинхронного ожидания в отдельном рабочем потоке, чтобы больше не блокировать основной поток пользовательского интерфейса.Вы можете создать свой собственный поток, который вызывает WaitForMultipleObjects()
(не MsgWaitForMultipleObjects()
, поскольку вам больше не нужно ждать в очереди сообщений), или вы можете использовать RegisterWaitForSingleObject()
для каждого дескриптора процесса в отдельности.В любом случае, пусть рабочий поток (-ы) уведомляет основной поток пользовательского интерфейса о завершении ожидания, и просто не вызывайте BidsConversion()
, пока не получите уведомление о завершении обоих процессов.