在form1构造函数
中cmd = " -i \"" + InputFile + "\" \"" + OutputFile + "\"";
backgroundWorker1.RunWorkerAsync();
然后
private void ConvertNow(string cmd)
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = exepath;
proc.StartInfo.Arguments = cmd;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
textBox1.Text = line;
}
}
然后在dowork事件中
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
ConvertNow(cmd);
}
问题在于行中的ConvertNow方法:
while (!proc.StandardOutput.EndOfStream)
我使用了一个断点并且它已经开始了,但是程序在此行之后挂起它从不进入字符串和textBox行。
我怎样才能使它可以在textBox中替换输出,或者可能在更好的控件中创建richTextBox或者其他东西?
这就是我现在尝试的:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Diagnostics;
namespace ConvertVideo
{
public partial class Form1 : Form
{
string InputFile = @"e:\lightningsmov\MVI_7909.MOV";
string OutputFile = @"e:\lightningsmov\MVI_7909.mp4";
string cmd;
string exepath = @"E:\myffmpegstatic\ffmpeg-20151217-git-9d1fb9e-win64-static\bin\ffmpeg.exe";
FileInfo fi;
public Form1()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.ProgressChanged += (sender, e) => textBox1.AppendText((string)e.UserState);
fi = new FileInfo(InputFile);
label2.Text = InputFile;
cmd = " -i \"" + InputFile + "\" \"" + OutputFile + "\"";
backgroundWorker1.RunWorkerAsync();
}
private void ConvertNow(string cmd)
{
try
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = exepath;
proc.StartInfo.Arguments = cmd;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
// use this event
proc.OutputDataReceived += (sender, e) => backgroundWorker1.ReportProgress(0, e.Data); // use this for synchronization
proc.Start();
// and start asynchronous read
proc.BeginOutputReadLine();
// wait until it's finished in your background worker thread
proc.WaitForExit();
}
catch(Exception err)
{
string myerr = err.ToString();
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
ConvertNow(cmd);
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
textBox1.Text = e.ProgressPercentage.ToString();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
}
}
当我在线上使用断点时:
proc.OutputDataReceived += (sender, e) => backgroundWorker1.ReportProgress(0, e.Data);
然后把我的鼠标放在proc上,我看到所有属性都有相同的例外:
BasePriority =' proc.BasePriority'抛出类型' System.InvalidOperationException'
的例外几乎所有的属性都是这样的。 试图添加尝试和捕捉,但它没有赶上捕获。
答案 0 :(得分:0)
您的代码中存在一些问题。最糟糕的是:您尝试从与UI线程不同的线程更新控件。
我建议您将ConvertNow
方法更改为以下内容:
private void ConvertNow(string cmd)
{
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = exepath;
proc.StartInfo.Arguments = cmd;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
// use this event
proc.OutputDataReceived += (sender, e) => backgroundWorker1.ReportProgress(0, e.Data); // use this for synchronization
proc.Start();
// and start asynchronous read
proc.BeginOutputReadLine();
// wait until it's finished in your background worker thread
proc.WaitForExit();
}
向您的后台工作人员添加ProgressChanged
事件(例如,在表单构造函数中):
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.ProgressChanged += (sender, e) => textBox1.AppendText((string)e.UserState);
现在,只要您的进程写入stdout,就会获得在UI线程上调用的事件,并将数据附加到文本框中。
更新:如果您已经拥有backgroundWorker1.ProgressChanged
的处理程序,则无需添加其他处理程序,但可以直接在处理程序中插入行textBox1.AppendText((string)e.UserState);
。但是如果你从我的其他部分调用backgroundWorker1.ReportProgress
,你应该首先检查e.UserState
是否实际上是一个应该添加到textBox的字符串。