I'm just starting out look in to delegates and async callbacks, but having some difficulties understanding this. I have this form and dont want to wait for string x = SR.ReadToEnd(); to complete, I want to get feedback to the form with string x = _streamreader.ReadLine(); after each update in the cmd instance.
How should I go about doing this?
From my understanding I cold create a delegate that holds x? and returns this to main thread each time it gets updated?
using System;
using System.Windows.Forms;
using System.Diagnostics;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
private string _command = "tracert www.google.com";
private string _application = "cmd";
private string _exitCommand = "exit";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
richTextBox1.Text += GetTrace();
}
private string GetTrace()
{
Process myprocess = new Process();
ProcessStartInfo StartInfo = new ProcessStartInfo();
StartInfo.FileName = _application;
StartInfo.RedirectStandardInput = true;
StartInfo.RedirectStandardOutput = true;
StartInfo.UseShellExecute = false;
StartInfo.CreateNoWindow = true;
myprocess.StartInfo = StartInfo;
myprocess.Start();
System.IO.StreamReader SR = myprocess.StandardOutput;
System.IO.StreamWriter SW = myprocess.StandardInput;
SW.WriteLine(_command);
SW.WriteLine(_exitCommand);
string x = SR.ReadToEnd();
SW.Close();
SR.Close();
return x;
}
}
}
UPDATE: from the tip of Erno i created a object to hold the value, and updates in a while loop, then i read the object in the update event. Is this a ok method to do this? or is there a cleaner way of doing this?
using System;
using System.Windows.Forms;
using System.Diagnostics;
namespace WindowsFormsApplication2
{
public class StringHolder
{
public string Buffer { get; set; }
}
public partial class Form1 : Form
{
private string x;
private const string Command = "tracert www.google.com";
private const string Application = "cmd";
private const string ExitCommand = "exit";
readonly StringHolder sh = new StringHolder();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object _sender, EventArgs _e)
{
GetTrace();
}
private void GetTrace()
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object _sender, System.ComponentModel.DoWorkEventArgs _e)
{
Process myprocess = new Process();
ProcessStartInfo StartInfo = new ProcessStartInfo();
StartInfo.FileName = Application;
StartInfo.RedirectStandardIn开发者_JAVA百科put = true;
StartInfo.RedirectStandardOutput = true;
StartInfo.UseShellExecute = false;
StartInfo.CreateNoWindow = true;
myprocess.StartInfo = StartInfo;
myprocess.Start();
System.IO.StreamReader _streamreader = myprocess.StandardOutput;
System.IO.StreamWriter _streamwriter = myprocess.StandardInput;
_streamwriter.WriteLine(Command);
_streamwriter.WriteLine(ExitCommand);
while (_streamreader.EndOfStream == false)
{
lock(sh)
{
sh.Buffer = _streamreader.ReadLine();
}
backgroundWorker1.ReportProgress(1, null);
}
_streamwriter.Close();
_streamreader.Close();
}
private void backgroundWorker1_ProgressChanged(object _sender, System.ComponentModel.ProgressChangedEventArgs _e)
{
lock(sh)
{
if (sh.Buffer != x)
{
richTextBox1.Text += "\n" + sh.Buffer;
}
x = sh.Buffer;
}
}
}
}
It appears that the Buffer property is only used to report the progress. If that indeed is the case, I'd just pass in the line that was read as a second parameter in the call to ReportProgress. Then in the ProgressChanged handler, it could be accessed with the UserState property. This would get rid of the Buffer and the associated lock
..............
sh.Buffer = _streamreader.ReadLine();
.........
private void backgroundWorker1_ProgressChanged(object _sender, System.ComponentModel.ProgressChangedEventArgs _e)
{
richTextBox1.Text += "\n" + _e.UserState;
}
Did you consider the BackgroundWorker? Using its ReportProgress event will make this easy.
The ReportProgress event only allows the passing of an integer (progress) but you could fill an object with some information (the string?) and use the ReportProgress event to warn the main thread. Make sure you use appropriate locks when reading/writing the object.
精彩评论