stream buffer issues

  • Thread starter Thread starter Radu Nica
  • Start date Start date
R

Radu Nica

Hey all,

I have an application that uses StreamReader and StreamWriter to call an
external command-line based process using the Process object. The process
varies the amount of data returned. I am using the StreamReader ReadtoEnd()
method to get the process' results.
Problem is, the application will work when returning a relatively small
amount of data, but after a certain threshold, the application will hang and
no data will be returned. From informal tests I've been running, it seems
there is a buffer issue somewhere (I suspect with the StreamReader).
How does one increase the size of the buffer? Are there advantages for using
ReadtoEnd vs. ReadLine? (I tried both ways and didn't seem to make a
difference)...

Thanks.
Radu
 
Radu Nica said:
I have an application that uses StreamReader and StreamWriter to call an
external command-line based process using the Process object. The process
varies the amount of data returned. I am using the StreamReader ReadtoEnd()
method to get the process' results.
Problem is, the application will work when returning a relatively small
amount of data, but after a certain threshold, the application will hang and
no data will be returned. From informal tests I've been running, it seems
there is a buffer issue somewhere (I suspect with the StreamReader).
How does one increase the size of the buffer? Are there advantages for using
ReadtoEnd vs. ReadLine? (I tried both ways and didn't seem to make a
difference)...

Are you sure it's not waiting for you to read from standard error as
well as standard output?
 
I have hit that issue before. The problem is the output stream will only
hold a small amount of data (like a page or something) before it is full -
then the process stalls as it can't write more output. And you can't
"readtoend" until the process stops or you kill it. You need to create
another thread that reads from stream until done.
The issue is mentioned here.
http://msdn.microsoft.com/library/d...iagnosticsprocessclassstandardoutputtopic.asp
I can't find my solution, but a sample solution is here (have not reviewed
the code in detail):
http://www.thecodeproject.com/csharp/LaunchProcess.asp#xx846829xx

hth
 
William Stacey said:
I have hit that issue before. The problem is the output stream will only
hold a small amount of data (like a page or something) before it is full -
then the process stalls as it can't write more output. And you can't
"readtoend" until the process stops or you kill it. You need to create
another thread that reads from stream until done.
The issue is mentioned here.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpre
f/html/frlrfsystemdiagnosticsprocessclassstandardoutputtopic.asp
I can't find my solution, but a sample solution is here (have not reviewed
the code in detail):
http://www.thecodeproject.com/csharp/LaunchProcess.asp#xx846829xx

Hang on though - the web page isn't saying that you can't ReadToEnd();
it's saying you can't just call ReadToEnd() *after* WaitForExit. I
think Radu's code should work fine *if* the application isn't also
writing to standard error. I suspect that's the problem here - it's not
that standard output isn't being read properly, it's that standard
error might be blocked, which stops the rest of the application.
 
Hang on though - the web page isn't saying that you can't ReadToEnd();
it's saying you can't just call ReadToEnd() *after* WaitForExit. I
think Radu's code should work fine *if* the application isn't also
writing to standard error. I suspect that's the problem here - it's not
that standard output isn't being read properly, it's that standard
error might be blocked, which stops the rest of the application.

Think I remember the issues I had now (forget stderror for now). ReadToEnd
before Wait works fine for all output unless you want to wait for some X
seconds. However if your process blocks/freezes for some reason you can't
waitforexit() because wait does not get called until ReadToEnd completes.
So if you want a generic method that reads all output *and gives you the
option to stop after some Wait (to not have zombies out there) then you need
to use another thread to read the stdout so you can WaitForExit with
timeout.
 
Here is something to build on...

private void button10_Click(object sender, System.EventArgs e)
{
int secTimeout = 1;
Thread stdOutReader = new Thread(new ThreadStart(ReadStdOut));
stdOutReader.IsBackground = true;
p = new Process(); // p private var.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd";
p.StartInfo.Arguments = @"/c dir c:\*.*; dir c:\*.*; dir c:\*.*";
p.Start();
stdOutReader.Start();
p.WaitForExit(secTimeout*1000); // Wait n seconds
if ( ! p.HasExited )
{
p.Kill();
stdOut = String.Format("Process killed after {0} second timeout.",
secTimeout);
}
else
{
stdOutReader.Join();
p.Close();
}
Console.WriteLine(stdOut); // stdOut private var.
}

private void ReadStdOut()
{
stdOut = p.StandardOutput.ReadToEnd();
}
 
Back
Top