Timing out a request to start a process... [Fernando Vicaria]

This is another post to quickly cover an question that I saw recently on one of our usergroups...

How do we create a process and "wait" for it begin running for a finite amount of time and if the process is not up and running until then timeout the request? I used the word wait in quotes because what the user really meant was that he makes the request in a separate thread while the application's main thread was still going on with its business. Of course there are at least half a dozen ways to do that but I decide to use the System.Threading.Timer class for this example.

The code below ilustrates this example:

using System;
using System.Diagnostics;
using System.Threading;

/// <summary>
/// Time-out process if it's not started or responding
/// </summary>
public class TimeOutProc
{
static int TIME_OUT = 2000; // in milliseconds

static public int Main()
{
// Comment out one of the next two lines...
//Process p = new Process();
Process p = Process.Start("notepad");

// Use Timeout.Infinite for the period to guarantee that
// the timer will fire only once.
Timer timer = new Timer(
new TimerCallback(TimeOut), p, TIME_OUT, Timeout.Infinite);

// This is just a trick so you can see the timer firing,
// in a real-life app you should not need this.
Console.WriteLine("Press any key to finish...");
Console.WriteLine();
Console.ReadLine();

// Get rid of timer when you're done.
timer.Dispose();
return 100;
}

// This is the callback method passed to the timer.
static void TimeOut(object state)
{
try
{
// Check if process has started and has a pid.
// If not this will throw a InvalidOperationException.
if (((Process)state).Id >= 0)
{
Console.WriteLine("Process has started...");

// Just for fun...
Console.WriteLine("Process is working OK. Kill it now!");
Thread.Sleep(2000);
((Process)state).Kill();

// You could also check if process is not responding
// instead...
if (!((Process)state).Responding)
{
Console.WriteLine("Process not responding...");
((Process)state).Kill();

// Optional: Make sure you have no dead object here.
state = null;
}
}
}
catch (System.InvalidOperationException)
{
Console.WriteLine("Process not ready...");
// Optional: Make sure you have no dead object here.
state = null;
}
}
}

As you can see I have added a call to Console.ReadLine() so that we could see the callback function firing. Another point to note is that we only want it to fire once and to accomplish that we pass Timeout.Infinite as the period parameter . We can test if the process has started by checking if it has a pid, if it does not what you get is an InvalidOperationException so we have to cover for this case.

Even if the process has a pid it does not mean that it's in a healthy state, it could be not responding for example. In that case we can just kill the process if we think that it's not the expected behavior after the timeout.