繁体   English   中英

如何在文本框中显示标准输出过程?

[英]How can i display a process StandardOutput in textBox?

在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;
            }
        }

然后在工作事件中

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'的异常

几乎所有类似的属性。 试图增加尝试并赶上来,但没有成功。

您的代码中存在一些问题。 最糟糕的情况:您尝试从不同于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是否实际上是应添加到e.UserState的字符串。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM