Как дождаться первого из двух: процесс и EventWaitHandle

Я хочу использовать WaitForMultipleObjects для двух разных типов:

  • 'EventWaitHandle'
  • 'Process.Handle' ==> intptr

Я не знаю, как преобразовать (подходящим образом) "process.Handle" в WaitHandle, чтобы работал следующий код:

   var waitHandles = new WaitHandle[2];
   waitHandles[0] = waitHandleExit;
   // Next line is the offending one:
   waitHandles[1] = new SafeWaitHandle(process.Handle, false);
   int waitResult = WaitHandle.WaitAny(waitHandles, timeOut);

Я получаю сообщение об ошибке:

Error   1   Cannot implicitly convert type 'Microsoft.Win32.SafeHandles.SafeWaitHandle' to 'System.Threading.WaitHandle' ...

Кто-нибудь знает, как правильно дождаться процесса и EventWaitHandle?

Обновление... Причины моего выбора ответа.

Прежде всего спасибо всем: Jaroen, Slugart и Sriram. Все ответы очень понравились.

  • Решение Jaroen по причине, которую я проигнорировал, не работало на моей машине. Мое событие "Exited" никогда не происходило (возможно, только при Disposed?).
  • Решение Slugart сработало отлично, и я попробовал его, прежде чем написал ответ.
  • Решение Sriram работало отлично, и я выбрал его, потому что я не создаю ложный EventWaitHandle и кажется более чистым в соответствии с моим видением.

Спасибо большое!!!


person Eric Ouellet    schedule 10.11.2014    source источник


Ответы (3)


Вы можете подкласса WaitHandle, который представляет Process.Handle, и использовать экземпляр этого WaitHandle для ожидания.

public class ProcessWaitHandle : WaitHandle
{
    private readonly Process process;
    public ProcessWaitHandle(Process process)
    {
        this.process = process;
        this.SafeWaitHandle = new SafeWaitHandle(process.Handle, false);
    }
}

var waitHandles = new WaitHandle[2]
{
    waitHandleExit,
    new ProcessWaitHandle(process)
};
int waitResult = WaitHandle.WaitAny(waitHandles, timeOut);
person Sriram Sakthivel    schedule 10.11.2014
comment
Почему false на new SafeWaitHandle? - person N-ate; 14.08.2018
comment
@N-ate, это параметр ownsHandle, который будет использоваться для освобождения базового дескриптора, если он равен true при удалении. Теперь, когда мы передали false, он не будет удалять дескриптор процесса. - person Sriram Sakthivel; 04.09.2018

Вы можете создать свой собственный EventWaitHandle и установить его в Process.Exited:

var waitHandle = new ManualResetEvent(false);
process.Exited += (sender, e) => waitHandle.Set()
waitHandles[1] = waitHandle;
person Jeroen Kok    schedule 10.11.2014
comment
Естественно, также необходимо установить EnableRaisingEvents, но весь этот подход излишне расточительный, когда дескриптор процесса ОС уже находится в режиме ожидания. - person Ben Voigt; 04.05.2021

Дескриптор процесса не является естественным образом ожидаемым и не находится в том же дереве наследования, что и WaitHandle. Вам нужно обернуть его в событие (которое расширяет WaitHandle), например:

 ManualResetEvent resetEvent = new ManualResetEvent(true);
 resetEvent.SafeWaitHandle = new SafeWaitHandle(new IntPtr(process.Handle.ToPointer()), false);
 waitHandles[1] = = resetEvent;

Все реализации WaitHandle будут использовать SafeWaitHandle: "Класс SafeWaitHandle используется классом System.Threading.WaitHandle. Это оболочка для мьютексов Win32 и событий автоматического и ручного сброса."

person Slugart    schedule 10.11.2014
comment
Не будет ли resetEvent.SafeWaitHandle = происходить утечка события, созданного конструктором ? - person Kevin Smyth; 13.01.2018