Johannes Johannes - 10 months ago 87
C# Question

Race conditition when using Process RedirectStandardError and RedirectStandardOutput,

I find myself in a race condition when subscribing to the output and error stream of

Here is a minimal example of what I do:

private string execute(string command, string arguments, int mstimeout)
string report = string.Empty;
StringBuilder output = new StringBuilder();
StringBuilder error = new StringBuilder();
Process p = new Process();
DataReceivedEventHandler ErrorDataReceived = (o, e) => { error.Append(e.Data); };
DataReceivedEventHandler OutputDataReceived = (o, e) => { output.Append(e.Data); };
p.StartInfo.FileName = command;
p.StartInfo.Arguments = arguments;
p.EnableRaisingEvents = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.OutputDataReceived += OutputDataReceived;
p.ErrorDataReceived += ErrorDataReceived;
report = output.ToString() + "\n" + error.ToString();
p.OutputDataReceived -= OutputDataReceived;
p.ErrorDataReceived -= ErrorDataReceived;
return report;

When debugging slowly the behaviour is what I hoped it would be. When running without stops the report ends up empty.

I assume there is a race condition where the underlying streaming objects are disposed before all the output was handled.

Is there something I can do to wait for all the output to be processed?

Answer Source

The problem was a timeout in certain situations. I needet to Kill the Process to avoid follow up issues.


For good measure I threw in a cleanup in the finally part that is likely not needet.

            p.OutputDataReceived -= OutputDataReceived;
            p.ErrorDataReceived -= ErrorDataReceived;
            p = null;
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: true);

Edit: I deleted the finally part since the comment below seems correct.

Edit: There was a deeper problem where the timeout was hit because of a required input. I ended up invoking a different command that is silent.