Conventional strategies for reading both StandardOut and StandardError involve helper methods and state objects similar to Listing 1
Listing 1: How it has been done:
public static void RunProcessConventional(string command, string args)
{
var proc = new Process
{
StartInfo =
{
UseShellExecute = false,
ErrorDialog = false,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
FileName = command,
Arguments = args
}
};
proc.Start();
var tOut = new Thread(ReadStream);
var outCtx = new StateObject {Reader = proc.StandardOutput};
tOut.Start(outCtx);
var errCtx = new StateObject {Reader = proc.StandardError};
var tErr = new Thread(ReadStream);
tErr.Start(errCtx);
proc.WaitForExit();
tOut.Join();
tErr.Join();
// state objects now contain the output
Console.WriteLine("\nOutput:\n----------------------------------\n{0}", outCtx.Output);
Console.WriteLine("\nError:\n----------------------------------\n{0}", errCtx.Output);
}
public static void ReadStream(object state)
{
var ctx = (StateObject) state;
ctx.Output = ctx.Reader.ReadToEnd();
}
#region Nested type: StateObject
public class StateObject
{
public string Output;
public StreamReader Reader;
}
#endregion
This strategy is fairly straight forward and there is nothing wrong with it, but, with the introduction of anonymous delegates, this code can be refactored to take features of the ‘closure’ created by the use of an anonymous delegate. These include the inline nature of the function to eliminate the need for a delegate target method and outer block variable visibility to eliminate the need for the ubiquitous ‘State’ object.
Listing 2: How it can be done now:
public static void RunProcessLambda(string command, string args)
{
var proc = new Process
{
StartInfo =
{
UseShellExecute = false,
ErrorDialog = false,
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
FileName = command,
Arguments = args
}
};
proc.Start();
string exception = null;
string output = null;
Thread tOut = new Thread(() => { output = proc.StandardOutput.ReadToEnd(); });
Thread tErr = new Thread(() => { exception = proc.StandardError.ReadToEnd(); });
tErr.Start();
tOut.Start();
proc.WaitForExit();
tErr.Join();
tOut.Join();
Console.WriteLine("\nOutput:\n----------------------------------\n{0}", output);
Console.WriteLine("\nError:\n----------------------------------\n{0}", exception);
}
Technorati tags:
C-Sharp,
CodeProject