获取反馈到主表单线程异步c#?

时间:2011-01-16 13:21:21

标签: c# asynchronous delegates

我刚刚开始查看代理和异步回调,但在理解这一点时遇到一些困难。我有这种形式,不想等待字符串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;
            }
        }
    }
}

2 个答案:

答案 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事件来警告主线程。确保在读/写对象时使用适当的锁。