C#运行多重非阻塞并联外部程序

C#运行多重非阻塞并联外部程序

问题描述:

我需要从我的应用程序运行外部可执行文件的多个实例。平均运行时间为这个可执行文件是约3分钟。
我想输出这些过程重定向,并更新我的GUI中的进度条。
我当然不希望等待他们回来之前,我可以继续使用我的应用程序。

I need to run several instances of an external executable from my app. The average run time for this executable is about 3 minutes. I want to redirect output from these processes, and update a progress bar in my GUI. Of course I don't want to wait for them to return before I can continue using my app.

我想我应该为每个实例创建一个线程和当一个线程完成更新我的进度条。

I think I should create a thread for every instance, and update my progress bar when a thread finishes.

这是正确的做法?

另外,你推荐一个很好的资源/文件,以了解它是如何工作的?我发现 http://www.dotnetperls.com/threadpool 只。

Also, do you recommend a good resource / documentation to understand how it works ? I've found http://www.dotnetperls.com/threadpool only.

编辑:这些过程是基于网络的,即:在运行时间可以有很大的差异取决于链路等待时间/带宽。

edit : these processes are network-based, ie: the run time may vary a lot depending on the link latency/bandwidth.

关于进度条,我想每一个进程完成的时间来更新它。是否有一个处理程序?后来我会添加更详细的更新,基于流程的输出,以增加每执行一步完成的进度

Concerning the progress bar, I would like to update it every time a process finishes. Is there a handler for that ? Later i will add more detailed update, based on the processes output to increase the progress done at each execution step.

编辑2:

感谢您的投入。正如我可能要运行大量程序的(最多20个),我不想饱和的带宽,我将在并行运行最多5。每次过程结束后,我递增进度计数器(我的进度条),我运行一个又一个,直到他们全部建成后,使用:

Thanks for your inputs. As I may have to run a lot of process (up to 20), and I don't want to saturate bandwidth, i'll run 5 in parallel max. Every time a process finishes, I increment the progress counter (for my progress bar) and I run another one until they're all completed, using :

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
}

它是正确的还是有一个更优雅的方式来实现这一目标?
我不想当然,执行过程中挡住了我的应用程序。
是它更好地使用背景工人为这个

Is it correct or is there a more elegant way to achieve this ? I don't want my app to be blocked during execution of course. Is it better to use background workers for this ?

您应该使用的 过程 和的 的ProcessStartInfo
你需要设置 ProcessStartInfo.UseShellExecute ErrorDialog RedirectStandardOutput 真正(也可能是 RedirectStandardError 太)。

You should be using Process and ProcessStartInfo. You'll need to set ProcessStartInfo.UseShellExecute to false, ErrorDialog to false, RedirectStandardOutput to true (and possibly RedirectStandardError too).

您将还需要提供一个委托到Process对象通过 OutputDataReceived 处理由外部进程生成的输出(也可能是 ErrorDataReceived 以及)。

You'll also need to provide a delegate to the Process object to handle to output generated by the external process through OutputDataReceived (and possibly ErrorDataReceived as well).

另外还有一个已退出委托可以设置将被调用每当进程退出。

There's also an Exited delegate you can set that will be called whenever the process exits.

例如:

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();