2016-10-10 33 views
1

我運行一個服務器,它是一個通過批處理執行的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#表單,我找不到任何結果如何使一個批處理包裝。

回答

0

調用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; 
        } 
       } 
      }); 
     } 
    } 
+0

所以,我嘗試使用此代碼,它運行得很好,但給了我,當我退出的出無輸出命令提示符。由於我是相當新的,我不知道你是否真的做出了將輸出設置到文本框的代碼,如果你沒有,我不知道應該在哪裏添加它。 –

+0

@CadeMartinez,您的信息,這裏是我忘了提及'textBox1'的一件事:'this.textBox1.Multiline = true;' –

+0

該文本框已經是多行,但是謝謝! –

相關問題