Process Question

G

Gidi

Hi,

I'm running a process from my application and using streamReader to read
it's output.

the file i'm running, writes some output to the screen and exceute another
program. I'm write the output i'm catching to a richTextBox.

my problem is that instead of dipalying line by line as the process works,
it waits till the process finishes and then updates the richTextBox.

how can i change it, so i will see the right flow in my textbox?

Thanks,
Gidi.
 
P

parez

Hi,

I'm running a process from my application and using streamReader to read
it's output.

the file i'm running, writes some output to the screen and exceute another
program. I'm write the output i'm catching to a richTextBox.

my problem is that instead of dipalying line by line as the process works,
it waits till the process finishes and then updates the richTextBox.

how can i change it, so i will see the right flow in my textbox?

Thanks,
Gidi.

one thing you could try is to flush the data from your process.
if your process is using Console.write the try Console.Out.Flush()
after every write. It mite work.
 
G

Gidi

Hi,

Thanks,

I using StreamReader to read the output, here is a sample from my code:

private void ReadStream(StreamReader sr)
{

string question = String.Empty;
int first_index = 0;
int last_index = 0;
string first_delim = "<Question>";
string last_delim = "<//Question>";

while (!sr.EndOfStream)
{
line = sr.ReadLine();

richTextBox1.Text += Environment.NewLine + line;
}


any ideas?

thanks,
Gidi.
 
G

Gidi

Hi Thanks,

it workes !!

Peter Duniho said:
Where is that code? How do you call it?

Regardless of the answer to that question, it's not correct code. If that
code is called from your main GUI thread, then it's blocking that thread,
preventing any GUI work at all until the other process ends. If that code
is not called from your main GUI thread, then it's missing the
all-critical call to Invoke() to interact with the richTextBox1.

I suspect the former is your problem. The solution would be for you to
run that code on a different thread, and replace the last line of code
with this:

richTextBox1.Invoke((MethodInvoker)delegate
{ richTextBox1.Text += Environment.NewLine + line; });

The code can be run on a different thread in a variety of ways. If you
expect this to always be a relatively short operation, you can simply use
the thread pool, either directly or via the BackgroundWorker class. If
the operation is likely to at least sometimes be longer (say, more than a
few seconds or so), then you may want to just create a new Thread instance
for each operation.

Pete
 
G

Gidi

Hi Peter,

one more question please.

I've now 2 threads, one is reading the streamOutput and one is writing to
the StreamInput.

i've a groupBox with buttons which is disabled till i need to use them. i
need to use them only when my streamReader is "stuck", meaning expecting an
input.

i tried to check the ThreadState, but it won't help.

i noticed that when the ReadThread is waiting for input it's state is
Background | WaitSleepJoin, so i tried this code:

if (c_ThreadRead.ThreadState != System.Threading.ThreadState.Background)
{

groupBox1.Invoke((MethodInvoker)delegate {
groupBox1.Enabled = true; });
}

but it doesn't help, because if the threadState is Background only it still
enables my groupBox.

any idea how can i fix that?

thanks a lot,
Gidi.
 
G

Gidi

Hi Peter, thanks.

I tried your first suggestion, and i still have the same problem.

the thing is that i have 2 threads running at the same time, one is reading
from the stream, and the other suppose to enable the groupBox if the reading
thread is stuck, but when i debugging, i see that when the second thread is
running, it threats the reading thread's state as
System.Threading.ThreadState.Background |
System.Threading.ThreadState.WaitSleepJoin

am i doing something wrong?

thanks so much for your help.

p.s.

the process i'm running is batch file who runns some other batch files, and
each batch file has output which i'm writing to the my richTextBox.


Peter Duniho said:
[...]
i've a groupBox with buttons which is disabled till i need to use them.. i
need to use them only when my streamReader is "stuck", meaning expecting
an
input.

i tried to check the ThreadState, but it won't help.

i noticed that when the ReadThread is waiting for input it's state is
Background | WaitSleepJoin, so i tried this code:

if (c_ThreadRead.ThreadState != System.Threading.ThreadState.Background)
{

groupBox1.Invoke((MethodInvoker)delegate {
groupBox1.Enabled = true; });
}

but it doesn't help, because if the threadState is Background only it
still
enables my groupBox.

The ThreadState enumeration is a flags enumeration. It seems unlikely to
me that it will ever _exactly_ equal ThreadState.Background.

Instead, you probably want something like:

groupBox1.Enabled = (c_ThreadRead.ThreadState &
ThreadState.WaitSleepJoin) == ThreadState.WaitSleepJoin;

Now, that said, I'm not exactly clear on where you're going to put this
code. It seems like the sort of thing that's in a polling loop, and
polling is generally something to be avoided.

One option would be enable the group just before reading, and then disable
it just after. That would work great if most of the time is spent waiting
on output. But if not, I think it would result in a fair amount of
flickering of the controls as they went back and forth between being
enabled and disabled.

Another alternative, and one that I think would probably work better,
would be to set a timer, and keep resetting it each time you successfully
read a line from your output. The timer interval would be some reasonable
timeout value, like a second or two, during which the control would remain
disabled. Only if the interval expires would you then enable the control.

That might look something like this (in your form class, using
System.Windows.Forms.Timer):

Timer _timer = new Timer();

void SomeMethodThatStartsEverything()
{
// do your process startup stuff, then
groupBox1.Enabled = false;
_timer.Interval = 1000;
_timer.Tick += TimerTickHandler;
_timer.Enabled = true;
}

void TimerTickHandler(object sender, EventArgs e)
{
_timer.Enabled = false;
groupBox1.Enabled = true;
}

void ReadStream(StreamReader sr)
{
string strLine;

while ((strLine = sr.ReadLine()) != null)
{
BeginInvoke((MethodInvoker)delegate
{
_timer.Enabled = false;
_timer.Enabled = true;
groupBox1.Enabled = false;
});

BeginInvoke((MethodInvoker)delegate
{ richTextBox1.Text += Environment.NewLine + strLine; });
}
}

Warning: I didn't compile that, so it might have some typos. Hopefully
you get the idea.

Also, note that I used BeginInvoke(). This isn't really necessary, but it
can potentially allow your code to run more efficiently by not forcing the
thread that's reading from the stream to keep yielding to your GUI
thread. Instead, the operations get added to the GUI thread's message
queue, to be processed whenever it next gets to run.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top