[英]Problem with System.Diagnostics.Process RedirectStandardOutput to appear in Winforms Textbox in real-time
我在實時從Winforms文本框中顯示控制台應用程序的重定向輸出時遇到問題。 消息是逐行生成的,但是,一旦要求與表單進行交互,就不會顯示任何內容。
遵循Stackoverflow和其他論壇上的許多示例之后,在過程完成之前,我似乎無法從過程中獲取重定向的輸出以顯示在表單的文本框中。
通過將調試行添加到'stringWriter_StringWritten'方法並將重定向消息寫入調試窗口,我可以看到在過程運行期間到達的消息,但是這些消息將在過程完成之前不會出現在表單的文本框中。
感謝對此的任何建議。
這是代碼的一部分
public partial class RunExternalProcess : Form
{
private static int numberOutputLines = 0;
private static MyStringWriter stringWriter;
public RunExternalProcess()
{
InitializeComponent();
// Create the output message writter
RunExternalProcess.stringWriter = new MyStringWriter();
stringWriter.StringWritten += new EventHandler(stringWriter_StringWritten);
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "myCommandLineApp.exe";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
using (var pProcess = new System.Diagnostics.Process())
{
pProcess.StartInfo = startInfo;
pProcess.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(RunExternalProcess.Process_OutputDataReceived);
pProcess.EnableRaisingEvents = true;
try
{
pProcess.Start();
pProcess.BeginOutputReadLine();
pProcess.BeginErrorReadLine();
pProcess.WaitForExit();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
finally
{
pProcess.OutputDataReceived -= new System.Diagnostics.DataReceivedEventHandler(RunExternalProcess.Process_OutputDataReceived);
}
}
}
private static void Process_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Data))
{
RunExternalProcess.OutputMessage(e.Data);
}
}
private static void OutputMessage(string message)
{
RunExternalProcess.stringWriter.WriteLine("[" + RunExternalProcess.numberOutputLines++.ToString() + "] - " + message);
}
private void stringWriter_StringWritten(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine(((MyStringWriter)sender).GetStringBuilder().ToString());
SetProgressTextBox(((MyStringWriter)sender).GetStringBuilder().ToString());
}
private delegate void SetProgressTextBoxCallback(string text);
private void SetProgressTextBox(string text)
{
if (this.ProgressTextBox.InvokeRequired)
{
SetProgressTextBoxCallback callback = new SetProgressTextBoxCallback(SetProgressTextBox);
this.BeginInvoke(callback, new object[] { text });
}
else
{
this.ProgressTextBox.Text = text;
this.ProgressTextBox.Select(this.ProgressTextBox.Text.Length, 0);
this.ProgressTextBox.ScrollToCaret();
}
}
}
public class MyStringWriter : System.IO.StringWriter
{
// Define the event.
public event EventHandler StringWritten;
public MyStringWriter()
: base()
{
}
public MyStringWriter(StringBuilder sb)
: base(sb)
{
}
public MyStringWriter(StringBuilder sb, IFormatProvider formatProvider)
: base(sb, formatProvider)
{
}
public MyStringWriter(IFormatProvider formatProvider)
: base(formatProvider)
{
}
protected virtual void OnStringWritten()
{
if (StringWritten != null)
{
StringWritten(this, EventArgs.Empty);
}
}
public override void Write(char value)
{
base.Write(value);
this.OnStringWritten();
}
public override void Write(char[] buffer, int index, int count)
{
base.Write(buffer, index, count);
this.OnStringWritten();
}
public override void Write(string value)
{
base.Write(value);
this.OnStringWritten();
}
}
pProcess.WaitForExit();
您正在用它掛UI線程。 在該過程退出之前,它不會像漆文本框那樣正常工作。 同樣,在UI線程再次變為空閑之前,BeginInvoke()委托目標無法運行。 它們將堆積在調用隊列中,在極端情況下,您將耗盡內存。 即使在進程退出后,UI線程在清空隊列時也會在一段時間內無響應。
您在這里不需要它。 如有必要,請改用Process.Exited事件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.