Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait for the first of the 2: a process and an EventWaitHandle

I want to WaitForMultipleObjects on 2 different types:

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

I don't know how to convert (in the appropriate way) "process.Handle" to a WaitHandle in order to have the following code working:

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

Im getting the error:

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

Anybody know the right way to wait for a process and an EventWaitHandle ?

Update... Reasons for my choice of answer.

First of all thanks to all: Jaroen, Slugart and Sriram. All answers were very nice.

  • Jaroen solution for a reason I ignored didn't work on my machine. My 'Exited' event never occured (perhaps only on Disposed?).
  • Slugart solution worked perfectly and I tried it before I red its answer.
  • Sriram solution worked perfectly and I opted for it because I do not create a false EventWaitHandle and seems to be more clean according to my vision.

Thanks a lots!!!

like image 657
Eric Ouellet Avatar asked Nov 10 '14 20:11

Eric Ouellet


3 Answers

You could subclass the WaitHandle which represents Process.Handle and use instance of that WaitHandle to wait.

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);
like image 145
Sriram Sakthivel Avatar answered Oct 02 '22 12:10

Sriram Sakthivel


You could create your own EventWaitHandle and set it on the Process.Exited event:

var waitHandle = new ManualResetEvent(false);
process.Exited += (sender, e) => waitHandle.Set()
waitHandles[1] = waitHandle;
like image 30
Jeroen Kok Avatar answered Oct 02 '22 12:10

Jeroen Kok


A process handle is not naturally awaitable nor does it sit in the same inheritance tree as WaitHandle. You need to wrap it in an event (which does extend WaitHandle), e.g.:

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

All WaitHandle implementations will use a SafeWaitHandle: "The SafeWaitHandle class is used by the System.Threading.WaitHandle class. It is a wrapper for Win32 mutexes and auto and manual reset events."

like image 35
Slugart Avatar answered Oct 02 '22 10:10

Slugart