我刚刚开始查看代理和异步回调,但在理解这一点时遇到一些困难。我有这种形式,不想等待字符串x = SR.ReadToEnd();要完成,我想通过字符串x = _streamreader.ReadLine()获得对表单的反馈;在cmd实例中的每次更新之后。
我该怎么做呢?
从我的理解,我冷创建一个持有x的委托?并在每次更新时将其返回给主线程?
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;
}
}
}
更新 从Erno的提示我创建了一个对象来保存值,并在while循环中更新,然后我在update事件中读取对象。这是一个好方法吗?或者有更清洁的方法吗?
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.RedirectStandardInput = 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;
}
}
}
}
答案 0 :(得分:2)
看来Buffer属性仅用于报告进度。如果情况确实如此,我只是传入在ReportProgress调用中作为第二个参数读取的行。然后在ProgressChanged处理程序中,可以使用UserState属性访问它。这将摆脱缓冲区和相关的锁
..............
sh.Buffer = _streamreader.ReadLine();
.........
private void backgroundWorker1_ProgressChanged(object _sender, System.ComponentModel.ProgressChangedEventArgs _e)
{
richTextBox1.Text += "\n" + _e.UserState;
}
答案 1 :(得分:1)
您是否考虑过BackgroundWorker?使用它的ReportProgress事件将使这变得容易。
ReportProgress事件只允许传递一个整数(进度)但你可以用一些信息(字符串?)填充一个对象,并使用ReportProgress事件来警告主线程。确保在读/写对象时使用适当的锁。