我正在为批处理程序制作包装器,但找不到实时更新输出的方法

I'm making a wrapper for a batch program and I can't find a way to update output in realtime

我运行一个服务器是一个jar文件,通过批处理执行。我试图为它制作一个包装器,但我找不到一种方法让批处理文件的输出在文本框上实时更新。

目前我使用的代码如下所示:

public partial class Form1 : Form
{

    string output = "Server has not been started yet...";

    public void button1_Click(object sender, EventArgs e)
    {
        Thread t = new Thread(batch); // Kick off a new thread
        t.Start(); // Running batch()

        Thread l = new Thread(loop);
        l.Start(); //Running loop
    }

    // This will run the batch file in the background
    public void batch()
    {
        Process p = new Process();
        p.StartInfo.UseShellExecute = false;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.FileName = "cmd.exe";
        p.StartInfo.Arguments = "/c @echo off";
        p.StartInfo.Arguments = "/c java -Xms512M -Xmx1G -XX:MaxPermSize=128M -XX:+UseConcMarkSweepGC -jar spigot.jar";
        p.Start();
        // reading to the end of its redirected stream.
        output = p.StandardOutput.ReadToEnd();

        // Can't do this because it only happens when the program
        // is exited and won't work cross-thread
        //textBox1.Text += output;
    }

    // Can't use this either because it will repeat messages
    // and it's still cross-thread
    //public void loop()
    //{
        //bool update = true;

        //while (update == true)
        //{
            //textBox1.Text += output;
        //}
    //}

如果没看过代码,基本上我的主要问题是不能跨线程更新文本框,不能使用循环,因为会重复消息,所以我不知道该怎么办。

我是 c# 表单的新手,我找不到关于如何制作批处理包装器的任何结果。

调用 textBox1.Invoke 可能是在您的情况下更新 GUI 控件的关键:

public partial class Form1 : Form
    {
        private object _sync;
        private ConcurrentQueue<string> _outputs;
        private bool _running;
        private delegate void OutputHandler(string line);
        private OutputHandler _append;

        public Form1()
        {
            InitializeComponent();
            _sync = new Object();
            _outputs = new ConcurrentQueue<string>();
            _append = new OutputHandler(line => {
                textBox1.AppendText(line + "\r\n");
            });
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var p = new Process();
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.OutputDataReceived += p_OutputDataReceived;
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.Arguments = "/c @echo off";
            p.StartInfo.Arguments = "/c java -Xms512M -Xmx1G -XX:MaxPermSize=128M -XX:+UseConcMarkSweepGC -jar spigot.jar";
            p.Start();
            p.BeginOutputReadLine();
            lock(_sync)
            {
                _running = true;
            }
            p.Exited += p_Exited;
            Task.Run(() => UpdateOutput());
        }

        void p_Exited(object sender, EventArgs e)
        {
            lock(_sync)
            {
                _running = false;
            }
        }

        void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if(e.Data != null)
            {
                _outputs.Enqueue(e.Data);
            }
        }

        private async Task UpdateOutput()
        {
            await Task.Run(() =>
            {
                var running = _running;
                while (running)
                {
                    var line = default(string);
                    if (_outputs.TryDequeue(out line))
                    {
                        try
                        {
                            textBox1.Invoke(_append, line);
                        }
                        catch
                        {

                        }
                    }
                    lock (_sync)
                    {
                        running = _running;
                    }
                }
            });
        }
    }