我需要从我的应用程序运行一个外部可执行文件的多个实例。该可执行文件的平均运行时间约为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设置为falseErrorDialog设置为falseRedirectStandardOutput设置为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();

10-04 22:21
查看更多