我需要从我的应用程序运行一个外部可执行文件的多个实例。该可执行文件的平均运行时间约为3分钟。
我想重定向这些过程的输出,并在GUI中更新进度条。
当然,我不想等他们回来再继续使用我的应用程序。
我认为我应该为每个实例创建一个线程,并在线程完成时更新进度条。
这是正确的方法吗?
另外,您是否推荐一个好的资源/文档以了解其工作原理?我只找到http://www.dotnetperls.com/threadpool。
编辑:这些过程是基于网络的,即:运行时间可能会变化很大,具体取决于链接延迟/带宽。
关于进度条,我想在每个过程完成时进行更新。有处理程序吗?稍后,我将根据输出的流程添加更详细的更新,以增加每个执行步骤所完成的进度。
编辑2:
感谢您的投入。由于我可能需要运行很多进程(最多20个),并且我不想饱和带宽,因此我将并行运行5个。每当一个进程完成时,我都会使用以下命令递增进度计数器(对于进度条),然后运行另一个计数器,直到它们全部完成为止:
Process p = new Process();
p.StartInfo.FileName = pathToApp;
p.EnableRaisingEvents = true;
p.Exited += OnCalibrationProcessExited;
p.Start();
private void OnCalibrationProcessExited(object sender, EventArgs e)
{
runAnotherOne function
}
是正确的还是有更优雅的方法来实现这一目标?
我当然不想在执行过程中阻止我的应用程序。
为此使用背景 worker 更好吗?
最佳答案
您应该使用 Process
和 ProcessStartInfo
。
您需要将ProcessStartInfo.UseShellExecute
设置为false
,ErrorDialog
设置为false
,RedirectStandardOutput
设置为true
(可能还有RedirectStandardError
)。
您还需要提供一个Process对象的委托(delegate),以处理外部进程通过OutputDataReceived
(可能还包括ErrorDataReceived
)生成的输出。
您还可以设置一个Exited
委托(delegate),该委托(delegate)将在进程退出时被调用。
例子:
ProcessStartInfo processInfo = new ProcessStartInfo("Write500Lines.exe");
processInfo.ErrorDialog = false;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
Process proc = Process.Start(processInfo);
proc.ErrorDataReceived += (sender, errorLine) => { if (errorLine.Data != null) Trace.WriteLine(errorLine.Data); };
proc.OutputDataReceived += (sender, outputLine) => { if (outputLine.Data != null) Trace.WriteLine(outputLine.Data); };
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();