Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#并行运行多个非阻塞外部程序_C#_Wpf_Multithreading_Process_External - Fatal编程技术网

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

C#并行运行多个非阻塞外部程序,c#,wpf,multithreading,process,external,C#,Wpf,Multithreading,Process,External,我需要从我的应用程序运行几个外部可执行文件的实例。此可执行文件的平均运行时间约为3分钟。 我想重定向这些进程的输出,并更新GUI中的进度条。 当然,我不想等到他们回来,我才能继续使用我的应用程序 我认为我应该为每个实例创建一个线程,并在线程完成时更新我的进度条 这是正确的方法吗 另外,您是否推荐一个好的资源/文档来了解它的工作原理?我只找到了一个 编辑:这些进程是基于网络的,即:运行时间可能会因链路延迟/带宽的不同而变化很大 关于进度条,我想在每次流程完成时更新它。有处理这件事的人吗?稍后,我将

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

我认为我应该为每个实例创建一个线程,并在线程完成时更新我的进度条

这是正确的方法吗

另外,您是否推荐一个好的资源/文档来了解它的工作原理?我只找到了一个

编辑:这些进程是基于网络的,即:运行时间可能会因链路延迟/带宽的不同而变化很大

关于进度条,我想在每次流程完成时更新它。有处理这件事的人吗?稍后,我将根据流程输出添加更详细的更新,以提高每个执行步骤的进度

编辑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
}
这是正确的还是有更优雅的方法来实现这一点? 当然,我不想在执行过程中阻止我的应用程序。
使用后台工作线程更好吗?

创建一个线程

在该线程中(伪代码):

请参阅等待退出

或者。。。是否要并行运行外部应用程序

编辑:基于原始帖子中的最新更新:

如果你不知道实际进度,那么就不要使用常规进度条。一个无限进度条或者一个“工作”图标怎么样


一个无限的进度条可以是一个进度条,它会填满整个进度条,并且从开始到完成所有事情。工作图标就像Windows忙光标(不断旋转的圆圈)。

创建一个线程

在该线程中(伪代码):

请参阅等待退出

或者。。。是否要并行运行外部应用程序

编辑:基于原始帖子中的最新更新:

如果你不知道实际进度,那么就不要使用常规进度条。一个无限进度条或者一个“工作”图标怎么样


一个无限的进度条可以是一个进度条,它会填满整个进度条,并且从开始到完成所有事情。工作图标类似于Windows忙光标(不断旋转的圆圈)。

只需通过调用构造函数创建多个Process类实例,将属性设置为重定向输出流,然后启动它们


只要不调用WaitForExit方法,程序就不会等待被调用的进程退出。不需要多线程。

只需通过调用构造函数创建Process类的几个实例,将属性设置为重定向输出流,然后启动它们


只要不调用WaitForExit方法,程序就不会等待被调用的进程退出。不需要多线程。

在更新进度条之前,只需等待每个线程结束,就不会产生任何结果。。。然后快速跳跃。。三次。您也可以跳过进度条

正确的方法是计算所有3个过程中完成的总功:

总工时=时间1+时间2+时间3

现在,如果您有多个处理器,它将需要更像max(time1,time2,time3),但这没关系。这是工作的表现

为完成的工作提供一个共享变量。每次流程执行更多的工作时,通过计算“已完成的工作+=我的工作增量”来更新进度栏。进度就是完成的工作/全部工作


无论线程是顺序运行还是并行运行,这都将提供良好的结果。由于您不知道事情将如何运行(您可能有一个单处理器cpu),因此这是最好的方法。

在更新进度条之前,只等待每个线程结束,不会导致任何结果。。。然后快速跳跃。。三次。您也可以跳过进度条

正确的方法是计算所有3个过程中完成的总功:

总工时=时间1+时间2+时间3

现在,如果您有多个处理器,它将需要更像max(time1,time2,time3),但这没关系。这是工作的表现

为完成的工作提供一个共享变量。每次流程执行更多的工作时,通过计算“已完成的工作+=我的工作增量”来更新进度栏。进度就是完成的工作/全部工作

无论线程是顺序运行还是并行运行,这都将提供良好的结果。因为您不知道事情将如何运行(您可能有一个单处理器cpu),这是最好的方法。

您应该使用和。 您需要将
ProcessStartInfo设置为
false
ErrorDialog
设置为
false
RedirectStandardOutput
设置为
true
(也可能是
RedirectStandardError

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

还有一个退出的
委托,您可以设置该委托,它将在流程退出时被调用

例如:

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();
你应该使用和。 您需要将
ProcessStartInfo设置为
false
ErrorDialog
设置为
false
RedirectStandardOutput
设置为
true
(也可能是
RedirectStandardError

您还需要为流程对象提供一个委托,以处理外部流程生成的输出
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();