Skip to content

Commit ebdba11

Browse files
author
Ron Petrusha
authored
Modified process output and error redirection members (#2048)
* Clarified example * Fixed broken links
1 parent 8563fb1 commit ebdba11

File tree

2 files changed

+61
-133
lines changed

2 files changed

+61
-133
lines changed

xml/System.Diagnostics/Process.xml

Lines changed: 30 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4313,44 +4313,22 @@ There are problems accessing the performance counter API's used to get process i
43134313
In contrast, <xref:System.Diagnostics.Process.BeginErrorReadLine%2A> starts asynchronous read operations on the <xref:System.Diagnostics.Process.StandardError%2A> stream. This method enables a designated event handler for the stream output and immediately returns to the caller, which can perform other work while the stream output is directed to the event handler.
43144314

43154315
Synchronous read operations introduce a dependency between the caller reading from the <xref:System.Diagnostics.Process.StandardError%2A> stream and the child process writing to that stream. These dependencies can result in deadlock conditions. When the caller reads from the redirected stream of a child process, it is dependent on the child. The caller waits on the read operation until the child writes to the stream or closes the stream. When the child process writes enough data to fill its redirected stream, it is dependent on the parent. The child process waits on the next write operation until the parent reads from the full stream or closes the stream. The deadlock condition results when the caller and child process wait on each other to complete an operation, and neither can proceed. You can avoid deadlocks by evaluating dependencies between the caller and child process.
4316-
4317-
The following C# code, for example, shows how to read from a redirected stream and wait for the child process to exit.
4318-
4319-
```csharp
4320-
// Start the child process.
4321-
Process p = new Process();
4322-
// Redirect the error stream of the child process.
4323-
p.StartInfo.UseShellExecute = false;
4324-
p.StartInfo.RedirectStandardError = true;
4325-
p.StartInfo.FileName = "Write500Lines.exe";
4326-
p.Start();
4327-
// Do not wait for the child process to exit before
4328-
// reading to the end of its redirected error stream.
4329-
// p.WaitForExit();
4330-
// Read the error stream first and then wait.
4331-
string error = p.StandardError.ReadToEnd();
4332-
p.WaitForExit();
4333-
```
4334-
4335-
The code example avoids a deadlock condition by calling `p.StandardError.ReadToEnd` before `p.WaitForExit`. A deadlock condition can result if the parent process calls `p.WaitForExit` before `p.StandardError.ReadToEnd` and the child process writes enough text to fill the redirected stream. The parent process would wait indefinitely for the child process to exit. The child process would wait indefinitely for the parent to read from the full <xref:System.Diagnostics.Process.StandardError%2A> stream.
4336-
4337-
There is a similar issue when you read all text from both the standard output and standard error streams. The following C# code, for example, performs a read operation on both streams.
4338-
4339-
```csharp
4340-
// Do not perform a synchronous read to the end of both
4341-
// redirected streams.
4342-
// string output = p.StandardOutput.ReadToEnd();
4343-
// string error = p.StandardError.ReadToEnd();
4344-
// p.WaitForExit();
4345-
// Use asynchronous read operations on at least one of the streams.
4346-
p.BeginOutputReadLine();
4347-
string error = p.StandardError.ReadToEnd();
4348-
p.WaitForExit();
4349-
```
4350-
4351-
The code example avoids the deadlock condition by performing asynchronous read operations on the <xref:System.Diagnostics.Process.StandardOutput%2A> stream. A deadlock condition results if the parent process calls `p.StandardOutput.ReadToEnd` followed by `p.StandardError.ReadToEnd` and the child process writes enough text to fill its error stream. The parent process would wait indefinitely for the child process to close its <xref:System.Diagnostics.Process.StandardOutput%2A> stream. The child process would wait indefinitely for the parent to read from the full <xref:System.Diagnostics.Process.StandardError%2A> stream.
4352-
4353-
You can use asynchronous read operations to avoid these dependencies and their deadlock potential. Alternately, you can avoid the deadlock condition by creating two threads and reading the output of each stream on a separate thread.
4316+
4317+
The last two examples in this section use the <xref:System.Diagnostics.Process.Start%2A> method to launch an executable named *Write500Lines.exe*. The following example contains its source code.
4318+
4319+
[!code-csharp[Executable launched by Process.Start](~/samples/snippets/csharp/api/system.diagnostics/process/standardoutput/write500lines.cs)]
4320+
[!code-vb[Executable launched by Process.Start](~/samples/snippets/visualbasic/api/system.diagnostics/process/standardoutput/write500lines.vb)]
4321+
4322+
The following example shows how to read from a redirected error stream and wait for the child process to exit. It avoids a deadlock condition by calling `p.StandardError.ReadToEnd` before `p.WaitForExit`. A deadlock condition can result if the parent process calls `p.WaitForExit` before `p.StandardError.ReadToEnd` and the child process writes enough text to fill the redirected stream. The parent process would wait indefinitely for the child process to exit. The child process would wait indefinitely for the parent to read from the full <xref:System.Diagnostics.Process.StandardError%2A> stream.
4323+
4324+
[!code-csharp[Reading from the error stream](~/samples/snippets/csharp/api/system.diagnostics/process/standarderror/stderror-sync.cs)]
4325+
[!code-vb[Reading from the error stream](~/samples/snippets/visualbasic/api/system.diagnostics/process/standarderror/stderror-sync.vb)]
4326+
4327+
There is a similar issue when you read all text from both the standard output and standard error streams. The following example performs a read operation on both streams. It avoids the deadlock condition by performing asynchronous read operations on the <xref:System.Diagnostics.Process.StandardError%2A> stream. A deadlock condition results if the parent process calls `p.StandardOutput.ReadToEnd` followed by `p.StandardError.ReadToEnd` and the child process writes enough text to fill its error stream. The parent process would wait indefinitely for the child process to close its <xref:System.Diagnostics.Process.StandardOutput%2A> stream. The child process would wait indefinitely for the parent to read from the full <xref:System.Diagnostics.Process.StandardError%2A> stream.
4328+
[!code-csharp[Reading from both streams](~/samples/snippets/csharp/api/system.diagnostics/process/standardoutput/stdoutput-async.cs)]
4329+
[!code-vb[Reading from both streams](~/samples/snippets/visualbasic/api/system.diagnostics/process/standardoutput/stdoutput-async.vb)]
4330+
4331+
You can use asynchronous read operations to avoid these dependencies and their deadlock potential. Alternately, you can avoid the deadlock condition by creating two threads and reading the output of each stream on a separate thread.
43544332

43554333
> [!NOTE]
43564334
> You cannot mix asynchronous and synchronous read operations on a redirected stream. Once the redirected stream of a <xref:System.Diagnostics.Process> is opened in either asynchronous or synchronous mode, all further read operations on that stream must be in the same mode. For example, do not follow <xref:System.Diagnostics.Process.BeginErrorReadLine%2A> with a call to <xref:System.IO.StreamReader.ReadLine%2A> on the <xref:System.Diagnostics.Process.StandardError%2A> stream, or vice versa. However, you can read two different streams in different modes. For example, you can call <xref:System.Diagnostics.Process.BeginOutputReadLine%2A> and then call <xref:System.IO.StreamReader.ReadLine%2A> for the <xref:System.Diagnostics.Process.StandardError%2A> stream.
@@ -4508,34 +4486,20 @@ p.WaitForExit();
45084486
In contrast, <xref:System.Diagnostics.Process.BeginOutputReadLine%2A> starts asynchronous read operations on the <xref:System.Diagnostics.Process.StandardOutput%2A> stream. This method enables a designated event handler for the stream output and immediately returns to the caller, which can perform other work while the stream output is directed to the event handler.
45094487

45104488
Synchronous read operations introduce a dependency between the caller reading from the <xref:System.Diagnostics.Process.StandardOutput%2A> stream and the child process writing to that stream. These dependencies can result in deadlock conditions. When the caller reads from the redirected stream of a child process, it is dependent on the child. The caller waits on the read operation until the child writes to the stream or closes the stream. When the child process writes enough data to fill its redirected stream, it is dependent on the parent. The child process waits on the next write operation until the parent reads from the full stream or closes the stream. The deadlock condition results when the caller and child process wait on each other to complete an operation, and neither can proceed. You can avoid deadlocks by evaluating dependencies between the caller and child process.
4511-
4512-
The following C# code, for example, shows how to read from a redirected stream and wait for the child process to exit.
4513-
4514-
```csharp
4515-
Process p = new Process();
4516-
p.StartInfo.UseShellExecute = false;
4517-
p.StartInfo.RedirectStandardOutput = true;
4518-
p.StartInfo.FileName = "Write500Lines.exe";
4519-
p.Start();
4520-
4521-
// To avoid deadlocks, always read the output stream first and then wait.
4522-
string output = p.StandardOutput.ReadToEnd();
4523-
p.WaitForExit();
4524-
```
4525-
4526-
The code example avoids a deadlock condition by calling `p.StandardOutput.ReadToEnd` before `p.WaitForExit`. A deadlock condition can result if the parent process calls `p.WaitForExit` before `p.StandardOutput.ReadToEnd` and the child process writes enough text to fill the redirected stream. The parent process would wait indefinitely for the child process to exit. The child process would wait indefinitely for the parent to read from the full <xref:System.Diagnostics.Process.StandardOutput%2A> stream.
4527-
4528-
There is a similar issue when you read all text from both the standard output and standard error streams. The following C# code, for example, performs a read operation on both streams.
4529-
4530-
```csharp
4531-
// To avoid deadlocks, use asynchronous read operations on at least one of the streams.
4532-
// Do not perform a synchronous read to the end of both redirected streams.
4533-
p.BeginOutputReadLine();
4534-
string error = p.StandardError.ReadToEnd();
4535-
p.WaitForExit();
4536-
```
4537-
4538-
The code example avoids the deadlock condition by performing asynchronous read operations on the <xref:System.Diagnostics.Process.StandardOutput%2A> stream. A deadlock condition results if the parent process calls `p.StandardOutput.ReadToEnd` followed by `p.StandardError.ReadToEnd` and the child process writes enough text to fill its error stream. The parent process would wait indefinitely for the child process to close its <xref:System.Diagnostics.Process.StandardOutput%2A> stream. The child process would wait indefinitely for the parent to read from the full <xref:System.Diagnostics.Process.StandardError%2A> stream.
4489+
4490+
The last two examples in this section use the <xref:System.Diagnostics.Process.Start%2A> method to launch an executable named *Write500Lines.exe*. The following example contains its source code.
4491+
4492+
[!code-csharp[Executable launched by Process.Start](~/samples/snippets/csharp/api/system.diagnostics/process/standardoutput/write500lines.cs)]
4493+
[!code-vb[Executable launched by Process.Start](~/samples/snippets/visualbasic/api/system.diagnostics/process/standardoutput/write500lines.vb)]
4494+
4495+
The following example shows how to read from a redirected stream and wait for the child process to exit. The example avoids a deadlock condition by calling `p.StandardOutput.ReadToEnd` before `p.WaitForExit`. A deadlock condition can result if the parent process calls `p.WaitForExit` before `p.StandardOutput.ReadToEnd` and the child process writes enough text to fill the redirected stream. The parent process would wait indefinitely for the child process to exit. The child process would wait indefinitely for the parent to read from the full <xref:System.Diagnostics.Process.StandardOutput%2A> stream.
4496+
4497+
[!code-csharp[Reading synchronously from a redirected output stream](~/samples/snippets/csharp/api/system.diagnostics/process/standardoutput/stdoutput-sync.cs)]
4498+
[!code-vb[Reading synchronously from a redirected output stream](~/samples/snippets/visualbasic/api/system.diagnostics/process/standardoutput/stdoutput-sync.vb)]
4499+
4500+
There is a similar issue when you read all text from both the standard output and standard error streams. The following example performs a read operation on both streams. It avoids the deadlock condition by performing asynchronous read operations on the <xref:System.Diagnostics.Process.StandardError%2A> stream. A deadlock condition results if the parent process calls `p.StandardOutput.ReadToEnd` followed by `p.StandardError.ReadToEnd` and the child process writes enough text to fill its error stream. The parent process would wait indefinitely for the child process to close its <xref:System.Diagnostics.Process.StandardOutput%2A> stream. The child process would wait indefinitely for the parent to read from the full <xref:System.Diagnostics.Process.StandardError%2A> stream.
4501+
[!code-csharp[Reading from a redirected output and error stream](~/samples/snippets/csharp/api/system.diagnostics/process/standardoutput/stdoutput-async.cs)]
4502+
[!code-vb[Reading from a redirected output and error stream](~/samples/snippets/visualbasic/api/system.diagnostics/process/standardoutput/stdoutput-async.vb)]
45394503

45404504
You can use asynchronous read operations to avoid these dependencies and their deadlock potential. Alternately, you can avoid the deadlock condition by creating two threads and reading the output of each stream on a separate thread.
45414505

0 commit comments

Comments
 (0)