这是个老话题了,可是折磨了我N个各月,我太笨了。某天终于很灵异地成功了,苦心人,天不负……![]()
现在还有太多的程序用命令行(为啥都喜欢用呢,看起来很professional?),可整天敲参数、看黑白屏幕总不太爽吧?![]()
GUI作用就是把这种“黑白屏幕”变成图形界面,看起来多舒服,是不是?![]()
最初这个问题是在x264编码器出现的。这是个命令行程序,想写个GUI。我真是自不量力呀,刚接触程序没几天就敢充胖子,一上来就碰壁,求google大神,有所收获。不过我模仿就是实现不了,太笨了。![]()
终于好了,有两个方法:一个是用StreamReader主动读取;另一个是用异步读取,应用回调函数。
个人认为前一种适合内容比较大多的情况,后一种适合比较少的情况。
先说第一种吧,
先引用需要的命名空间
2 using System.Threading;
2 delegate void chandle(string s);
{
Thread tt = new Thread(new ThreadStart(t));
tt.Start();
}
在这里,新建了一个线程,我可不喜欢在主线程上跑,影响美观,下面写t()这个方法。
2 {
3 p = new Process();
4 p.StartInfo.FileName = "azid.exe";
5 p.StartInfo.Arguments = @"I:\kn\m12\m12..ac3 I:\kn\m12\au2.wav";
6
7 p.StartInfo.CreateNoWindow = true;
8 p.StartInfo.UseShellExecute = false;
9 p.StartInfo.RedirectStandardError = true;
10
11
12
13 p.Start();
14
15 Thread rt = new Thread(new ThreadStart(read));
16 rt.Start();
17 p.WaitForExit();
18
19 p.Dispose();
20 }
21
在这里,创建一个Process类的实例,然后对StartInfo属性进行设置,主要是为了不要让他显示命令行窗口,并且把输出流RedirectStandardError导出,
这里多说一句,我这个程序azid的输出都被塞到了StandardError(标准错误输出)里面,貌似x264也是,你要注意一下你的程序输出是在标准输出还是错误输出,依次尝试一下即可,之后再创建一个线程,用来运行我们的读取函数,具体关系看下面这张涂鸦。
下面写读取函数read()
2 {
3 StreamReader sr = p.StandardError;
4 while (!p.HasExited)
5 {
6 Invoke(new chandle(ct), sr.ReadLine());
7 Thread.Sleep(20);
8 }
9 }
这里用Invoke来控制主界面上的控件,因为这里是线程rt,不能直接操作主线程厄,我在这里弱智了N久,一直研究怎么做线程同步,其实是迷失了方向,偶然才发现Invoke方法的强大。![]()
这里挂接的委托ct用来更新主界面的textbox,显示读取出来的内容,把sr.ReadLine()做参数传进去。
2 {
3 textBox1.AppendText(s.Trim() + "\n");
4 textBox1.SelectionStart = textBox1.Text.Length - 1;
5 Application.DoEvents();
6 }
下面说说异步读取,这个好像比上面的简单。
2 delegate void chandle(string s);
3
4
5 private void button1_Click(object sender, EventArgs e)
6 {
7 Thread tt = new Thread(new ThreadStart(t));
8 tt.Start();
9 }
10 private void t()
11 {
12 p = new Process();
13 p.StartInfo.FileName = "azid.exe";
14 p.StartInfo.Arguments = @"I:\kn\m12\m12..ac3 I:\kn\m12\au2.wav";
15 p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);//这里多了这句
16 p.StartInfo.CreateNoWindow = true;
17 p.StartInfo.UseShellExecute = false;
18 p.StartInfo.RedirectStandardError = true;
19 p.Start();
20 p.BeginErrorReadLine(); //这里多了这句
21 p.WaitForExit();
22
23 p.Dispose();
24 }
25
2 {
3 if (!string.IsNullOrEmpty(e.Data))
4 {
5 // 做点工作
6 }
7 }
程序每向输出流写入一行时,触发一次这个事件,e.Data属性可以获得这一行数据,然后怎么处理就看你了。
这个方法如果你的输出流行数很多,那就要不断地调用这个函数,很费资源orz,到底用哪个,根据情况判断吧,当然你也可以2个交错使用,在msdn上有写限制条件
地址在这里:http://msdn.microsoft.com/zh-cn/library/system.diagnostics.process.standarderror(VS.80).aspx
浙公网安备 33010602011771号