I have a process that runs in the background and has WaitForExit()
, since the duration may vary and I need to wait till it finishes. On occasions, I need to end it before it completes and I trigger .Kill()
command via a class event. The .HasExited
property changes to true but the code never gets passed the WaitForExit()
line.
public class MyProcess: Process
{
private bool exited;
public MyProcess()
{
...
}
public void Start(args...)
{
try
{
base.StartInfo.FileName = ...
base.StartInfo.Arguments = ...
base.StartInfo.RedirectStandardOutput = true;
base.StartInfo.UseShellExecute = false;
base.StartInfo.CreateNoWindow = true;
base.EnableRaisingEvents = true;
base.Exited += new EventHandler(MyProcessCompleted);
base.OutputDataReceived += new DataReceivedEventHandler(outputReceived);
base.Start();
this.exited = false;
base.BeginOutputReadLine();
while (!this.exited)
{
if ()
{
...
}
else
{
base.WaitForExit(); ---- after the process is killed, it never gets past this line.
}
...
}
}
catch (Exception ex)
{
...
}
}
private void MyProcessCompleted(object sender, System.EventArgs e)
{
exited = true;
...
}
private void outputReceived(object sender, DataReceivedEventArgs e)
{
...
}
//Subscription to cancel event
public void ProcessCanceled(object sender, EventArgs e)
{
...
if (!exited)
{
base.Kill();
}
}
}
\
UPDATE:
My process launches a java based file transfer client and performs a transfer. The process shows up in the task manager and Kill()
does not end it. Since I don't really care about ending the process but rather need my program to go to the next "task", I added Close()
right after Kill()
, which releases the WaitForExit
and lets my code "move on". Terminating the process early will be a rare occurance in my app, but I still need it to work, so this implementation will have to do.
}
WaitForExit
is a direct call to the OS to wait for the process handle to become signaled. When a process terminates, WaitForExit
will complete. Kill
is a direct call to TerminateProcess
which is a kill with no questions asked. If used correctly WaitForExit
will return after Kill
has completed.
So there is some other bug in your code. Create a simpler repro and you will see the issue disappear. The bug is hidden in the complexity of your code.
Or, WaitForExit
did return but you did not notice. Or, Kill
was never executed or failed. Again, simplifying the code will reveal the issue. Can you bring it down to a 5 line repro? I doubt you can, but I will look again if you do.
Try this:
Process p = Process.Start("notepad.exe");
Task.Factory.StartNew(() => { Thread.Sleep(1000); p.Kill(); });
p.WaitForExit();
Update:
In the comments you specified that killing ping does work, but killing your special process doesn't. The cause for this usually is non-cancellable IO. The Windows kernel keeps processes around until all IO is done. The good news is that the process will die eventually and no code will run after Kill
has returned. The bad news is that resource cleanup is not fully completed.
You now need to ensure that your code can move on although WaitForExit
did not return. To do that I'd set a ManualResetEvent after Kill
has completed. And instead of calling WaitForExit
, you obtain the process handle using the Process.Handle
property and wait on either of the two waitables to become signaled. Look at what WaitForExit
does internally to see how you could implement this yourself (I'd copy out the ProcessWaitHandle
class which is internal).
A simpler solution would be to call WaitForExit(TimeSpan.FromMilliseconds(100))
in a loop and check the exited
flag each time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With