-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
When writing code that creates child processes and needs to capture stdout, I have found that lines of output go missing the following condition:
- lots of parallelism...
ProcessStartInfo.RedirectStandardOutput = trueProcess.OutputDataReceived += CollectLines(that is, using the async flow)Process.BeginOutputReadLine()Process.WaitForExit(int.MaxValue)
Note that passing -1 (infinite timespan) to WaitForExit does not cause lines go missing (based on my own testing).
I have created a little demo app to do this. It repro's on both netcoreapp1.0 and net45: processredirect.zip. Just use dotnet run to try it out.
That being said, you can capture stdout by using Process.StandardOutput (which is a StreamReader). However to consume this asynchronously and safely you need to use background threads/tasks. In other words:
| stdout capture method | using infinite timeout | is flaky |
|---|---|---|
StandardOutput StreamReader |
yes | no |
StandardOutput StreamReader |
no | no |
OutputDataReceived event |
yes | no |
OutputDataReceived event |
no | yes |
I think this a problem because it's pretty easy to step into this pitfall. Using the events to capture output is very convenient since you don't have to worry about making background threads or tasks. Also, the internet recommends this method:
- http://stackoverflow.com/questions/285760/how-to-spawn-a-process-and-capture-its-stdout-in-net
- https://msdn.microsoft.com/en-us/library/system.diagnostics.process.beginoutputreadline(v=vs.110).aspx
I have only tried this on Windows, .NET Framework 4.5 and .NET Core (netcoreapp1.0). Also, all of this information is related to stdout, but I imagine stderr has the same problem. My dotnet info is:
Microsoft .NET Core Shared Framework Host
Version : 1.0.1
Build : cee57bf6c981237d80aa1631cfe83cb9ba329f12
> dotnet --version
1.0.0-preview2-003131