#c# #wrapper
#c# #оболочка
Вопрос:
Я запускаю сервер, который представляет собой файл 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 # forms и не могу найти никаких результатов о том, как создать пакетную оболочку.
Ответ №1:
Вызов 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 "rn");
});
}
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;
}
}
});
}
}
Комментарии:
1. Итак, я попробовал использовать этот код, и он работает просто отлично, но не выдает никаких результатов при выходе из командной строки. Поскольку я довольно новичок, я не знаю, действительно ли вы создали код, который устанавливает выходные данные в текстовое поле, и если вы этого не сделали, я не знаю, куда мне его добавить.
2. @CadeMartinez, для вашей информации, вот одна вещь, о которой я забыл упомянуть
textBox1
:this.textBox1.Multiline = true;