對於太長時間,我一直在嘗試運行一個外部.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