【问题标题】:C# Batch file output problemsC#批处理文件输出问题
【发布时间】:2014-04-15 12:20:34
【问题描述】:

我一直在为 Minecraft 服务器开发一个管理器应用程序,当我运行我的程序时,控制台显示并消失,如果我手动运行它,它运行没有问题。 批处理文件代码:

java -Xmx1024M -jar craftbukkit-1.7.2-R0.3.jar -o false

我的完整代码(MessageBoxes 是波兰语,因为我来自波兰,但稍后我会添加对其他语言的支持):

using System;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public Process server;

        private Boolean runServer()
        {
            if (!File.Exists(textBox2.Text))
            {
                MessageBox.Show("Brak określonej ścieżki dostępu! (" + textBox2.Text + ")", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            Process process = new Process
            {
                StartInfo =
                {
                    FileName = textBox2.Text,
                    //Arguments = textBox3.Text,
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    CreateNoWindow = false,
                }
            };

            process.OutputDataReceived += new DataReceivedEventHandler(server_outputDataReceived);
            process.ErrorDataReceived += new DataReceivedEventHandler(server_outputDataReceived);
            server = process;

            if (process.Start())
                return true;
            else
            {
                MessageBox.Show("Nie można włączyć serwera!", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        private String ReadFile(String filename, int line)
        {
            StreamReader reader = new StreamReader(filename);

            for (int i = 0; i < line; i++)
            {
                reader.ReadLine();
            }

            return reader.ReadLine();
        }

        private void ReloadOPs()
        {
            if (!File.Exists(textBox1.Text))
            {
                MessageBox.Show("Sciezka dostępu do pliku z listą graczy posiadających OP nie istnieje! (" + textBox1.Text + ")", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                tabControl1.SelectedTab = tabPageOptions;
                textBox1.SelectAll();
                return;
            }

            String line = ReadFile(textBox1.Text, 0);
            comboBox1.Items.Clear();
            for (int i = 1; i < File.ReadAllLines(textBox1.Text).Length; i++)
            {
                if (!String.IsNullOrWhiteSpace(ReadFile(textBox1.Text, i)))
                {
                    comboBox1.Items.Add(line);
                    line = ReadFile(textBox1.Text, i);
                }
            }

            MessageBox.Show("Lista graczy z OP, została odświeżona.");
        }

        // OPs combobox (OPs)
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            groupBox1.Text = comboBox1.SelectedItem.ToString();
            groupBox1.Visible = true;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.Text = Application.StartupPath.ToString() + @"\ops.txt";
            ReloadOPs();
        }

        // Reload OPs button (OPs)
        private void button1_Click(object sender, EventArgs e)
        {
            ReloadOPs();
        }


        // Save button (Options)
        private void button4_Click(object sender, EventArgs e)
        {

        }

        private void server_outputDataReceived(object sender, DataReceivedEventArgs e)
        {
            addConsoleMessage(e.Data.ToString(), true);
        }

        // Run server button (Menu)
        private void button5_Click(object sender, EventArgs e)
        {
            if (!runServer())
                return;

            server.BeginOutputReadLine();
            button6.Enabled = true;
        }

        // Stop server button (Menu)
        private void button6_Click(object sender, EventArgs e)
        {
            if(!server.HasExited)
                server.Kill();
            button6.Enabled = false;
        }

        private void addConsoleMessage(String message, Boolean refresh)
        {
            listBox1.Items.Add(message);
            if (refresh)
                listBox1.Refresh();
        }
    }
}

我的问题是程序崩溃,因为 InvaildOperationException 未处理(addConsoleMessage 中的 listBox1.Items.Add(message))。 外部错误信息:线程之间的无效操作:控件“listBox1”是从它创建的线程以外的线程访问的。

【问题讨论】:

  • 设置断点并调试addConsoleMessage函数并检查究竟是什么导致它抛出异常。
  • 它抛出 InvalidOperationException 因为,(正如它所说)“线程之间的无效操作:控件 'listBox1' 是从它创建的线程之外的线程访问的。”

标签: c# batch-file


【解决方案1】:

您无法更新 UI 表单后台线程。试试这个

WPF

    private void server_outputDataReceived(object sender, DataReceivedEventArgs e)
    {
        Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, () =>
                {
                     addConsoleMessage(e.Data.ToString(), true);
                });
    }

更新

在 WinForms 中,Invoke/BeginInvoke 方法直接在控件对象上,您可以从 System.Windows.Forms.Control 的文档中看到。所以你会有 listBox1.BeginInvoke(...) 例如。

【讨论】:

  • 命名空间“System.Windows”中不存在类型或命名空间名称“Threading”(您是否缺少程序集引用?)
  • 这似乎回答了一个针对 WPF 的问题,但 OP 使用的是 WinForm public partial class Form1 : Form
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 2013-08-27
  • 2014-01-15
  • 2015-05-03
  • 1970-01-01
相关资源
最近更新 更多