Given the following code and assuming process.OutputDataReceived
and process.ErrorDataReceived
are accessing the same resource, can race conditions occur?
var process = new Process();
process.OutputDataReceived += ...
process.ErrorDataReceived += ...
Given the following code and assuming process.OutputDataReceived
and process.ErrorDataReceived
are accessing the same resource, can race conditions occur?
var process = new Process();
process.OutputDataReceived += ...
process.ErrorDataReceived += ...
Share
Improve this question
asked Jan 19 at 20:06
me.at.codingme.at.coding
17.9k48 gold badges180 silver badges342 bronze badges
6
|
Show 1 more comment
1 Answer
Reset to default 3It depends on several factors including the process you are running - it can write simultaneously to stdout and stderr. It is easy to check:
Writer:
var iterations = 2000;
var stdout = Task.Run(() =>
{
for (var i = 0; i < iterations; i++)
{
Console.Out.WriteLine(i);
}
});
var stderr = Task.Run(() =>
{
for (var i = 0; i < iterations; i++)
{
Console.Error.WriteLine(i);
}
});
await Task.WhenAll(stdout, stderr);
Capturer:
var process = new Process();
int c = 0;
int @out = 0;
int err = 0;
process.StartInfo = new ProcessStartInfo
{
UseShellExecute = false,
FileName = "dotnet",
Arguments = $"{PathToWriterReleaseFolder}/Writer.dll",
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true
};
process.OutputDataReceived += (sender, args) =>
{
if (!string.IsNullOrEmpty(args.Data))
{
c++;
@out++;
}
};
process.ErrorDataReceived += (sender, args) =>
{
if (!string.IsNullOrEmpty(args.Data))
{
c++;
err++;
}
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
Console.WriteLine(c);
Console.WriteLine(@out);
Console.WriteLine(err);
Which gives something like (on my machine - Ubuntu):
3983
2000
2000
Which clearly shows race condition (first number may vary between runs).
Also check the docs for Process.OutputDataReceived/ErrorDataReceived
and Process.BeginOutputReadLine/BeginErrorReadLine
which explicitly state that this handling is asyncronious:
The event is enabled during asynchronous read operations on
StandardOutput
. To start asynchronous read operations, you must redirect theStandardOutput
stream of aProcess
, add your event handler to theOutputDataReceived
event, and callBeginOutputReadLine
. Thereafter, theOutputDataReceived
event signals each time the process writes a line to the redirectedStandardOutput
stream, until the process exits or callsCancelOutputRead
.
And
The event only occurs during asynchronous read operations on
StandardError
. To start asynchronous read operations, you must redirect theStandardError
stream of aProcess
, add your event handler to theErrorDataReceived
event, and callBeginErrorReadLine
. Thereafter, theErrorDataReceived
event signals each time the process writes a line to the redirectedStandardError
stream, until the process exits or callsCancelErrorRead
.
OutputDataReceived
andErrorDataReceived
– Luuk Commented Jan 19 at 20:11lock
makes it trivial. – Hans Passant Commented Jan 19 at 22:43