对于太长时间,我一直在尝试运行一个外部.bat文件(为某些统计处理调用R脚本),并将控制台重定向到U.I.在主线程处于活动状态时BackgroundWorker线程不会触发
我觉得我很接近,但正如我已经得到它的工作,我遇到了一个相当大的问题!也就是说:只有当主线程结束时(通过:return;),而不是Thread.Sleep或.WaitOne()等时,才会进行血腥的工作。
这是我在主线程中的代码。
string batLoc = ALLRG___.RSCRBIN_LOC + "current.bat";
BackgroundWorker watchboxdWorker1 = new BackgroundWorker();
watchboxdWorker1.DoWork += frmC.WatchboxWorker1_WatchExt;
frmC.wbResetEvent = new AutoResetEvent(false);
watchboxdWorker1.RunWorkerAsync(batLoc);
//Thread.Sleep(1000*20);
//frmC.wbResetEvent.WaitOne();
return;
请注意注释掉Sleep和/或WaitOne()指令。如果我尝试并使用这些BackgroundWorker执行,但更新U.I的'事件'不会。
在我的表单的代码(以上FRMC)如下,
public void WatchboxWorker1_WatchExt(object sender, DoWorkEventArgs e)
{
string exeLoc = (string) e.Argument;
string arg1 = exeLoc;
string arg2 = "";
ProcessStartInfo pStartInfo = new ProcessStartInfo();
pStartInfo.FileName = exeLoc;
pStartInfo.Arguments = string.Format("\"{0}\" \"{1}\"", arg1, arg2);
pStartInfo.WorkingDirectory = Path.GetDirectoryName(exeLoc);
pStartInfo.CreateNoWindow = true;
pStartInfo.UseShellExecute = false;
pStartInfo.RedirectStandardInput = true;
pStartInfo.RedirectStandardOutput = true;
pStartInfo.RedirectStandardError = true;
Process process1 = new Process();
process1.EnableRaisingEvents = true;
process1.OutputDataReceived += new DataReceivedEventHandler(wbOutputHandler);
process1.ErrorDataReceived += new DataReceivedEventHandler(wbErrorHandler);
process1.StartInfo = pStartInfo;
process1.SynchronizingObject = rtbWatchbox;
process1.Start();
process1.BeginOutputReadLine();
process1.BeginErrorReadLine();
process1.StandardInput.Close();
process1.WaitForExit();
wbResetEvent.Set();
}
public void wbOutputHandler(Object source, DataReceivedEventArgs outLine)
{
int x = 0;
if (!String.IsNullOrEmpty(outLine.Data))
{
rtbWatchbox.AppendText(outLine.Data);
}
}
public void wbErrorHandler(Object source, DataReceivedEventArgs outLine)
{
int x = 0;
if (!String.IsNullOrEmpty(outLine.Data))
{
rtbWatchbox.AppendText(outLine.Data);
}
}
我的问题是 -
的wbOutputHandler和wbErrorHandler得到很好地解雇作为控制台更新 - 但只有当主如果我在主线程中使用Thread.Sleep或.WaitOne()将控制传递给BackgroundWorker(WatchboxWorker1_WatchExt),那么代码将成功运行,但wbOutputHandler和wbErrorHandler方法根本不会被触发。实际上,如果我执行Thread.Sleep(10 * 1000),那么外部程序按计划开始运行,传递10秒,然后当主UI线程退出时,我会立即得到一个大的巨大更新。
我不想让我的主线程关闭,我想在工作完成后继续在那里做东西!
[用于替代方法是一个更好的办法当然高兴]“帮我堆栈溢出,你是我唯一的希望!”
您不会登录到“控制台”,而是登录到某个“RichtTextBox”右边?所以这是一个WinForms应用程序 - 然后问题是:运行UI的代码在哪里(有点像Application.Run(new Form1());')?顺便说一句:当然UI不会更新,如果你阻止它的线程... – Carsten 2014-10-05 06:35:43
PS:如果你不以这种方式退出你的应用程序,你不需要阻止! – Carsten 2014-10-05 06:36:44
谢谢Carsten你神奇地有帮助。 – 2014-10-06 09:40:14