如何设置程序可以同时启动的最大外部进程数?

时间:2012-06-18 15:41:53

标签: c# windows process queue

我需要为指定目录中的每个PDF文件运行一个外部程序。

问题是 - 如何将外部程序进程的数量限制为用户指定的值?我在循环中运行它,如下所示:

foreach(string file in Directory.GetFiles(sourcePath))
{
    Process p = new Process();
    p.StartInfo.FileName = @"path\program.exe";
    p.StartInfo.Arguments = previouslySetArguments;
    p.Start();
}

现在的问题是,有时存在大量文件,并且使用该代码,所有进程都将同时运行。它确实减慢了机器的速度。

其他想法是将p.WaitForExit();放在p.Start();之后,但它会一次只运行一个进程,另一方面 - 减慢整个工作:)

限制进程号以同时运行其确切数量的最简单方法是什么?我想让用户决定。

假设我想一次运行最多5个进程。所以:
  - 对于目录中的前5个文件,前5个进程或多或少同时启动   - 当其中一个(无关紧要,哪个)结束工作时,下一个开始 - 为下一个文件

2 个答案:

答案 0 :(得分:0)

如果我是你,我会研究排队的生产者 - 消费者模型。它的目的很准确,并且有很多很好的例子可以根据您的需要进行修改。

这是一个例子: C# producer/consumer

另一个例子: http://msdn.microsoft.com/en-us/library/hh228601%28v=vs.110%29.aspx (最后一个是4.5,但仍然是有效的IMO)

答案 1 :(得分:0)

好的,所以我尝试了this question的答案,但是 - 奇怪的是 - 我无法让它们起作用。我承认,我很匆忙,我可能犯了一些错误......

现在,我发现的最快速,最简单(也是最丑陋)的方法只是一个循环,就像下面的代码一样。它适用于仅使用给定命令行参数调用Thread.Sleep()的测试程序作为毫秒。

现在,请解释我,为什么它不是一个好的解决方案 - 我认为这不是正确的方法(不仅因为代码很难看),即使它适用于此测试示例

class Program
{
    // hardcoded, it's just a test:
    static int activeProcesses = 0;
    static int finishedProcesses = 0;
    static int maxProcesses = 5;
    static int runProcesses = 20;

    static string file = @"c:\tmp\dummyDelay.exe";

    static void Main(string[] args)
    {
        Random rnd = new Random();

        while (activeProcesses + finishedProcesses < runProcesses)
        {
            if (activeProcesses < maxProcesses)
            {
                Process p = new Process();
                p.EnableRaisingEvents = true;
                p.Exited += new EventHandler(pExited);
                p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                p.StartInfo.FileName = file;
                p.StartInfo.Arguments = rnd.Next(2000, 5000).ToString();
                p.Start();
                Console.WriteLine("Started: {0}", p.Id.ToString());
                activeProcesses++;
            }
        }

    }

    static void pExited(object sender, EventArgs e)
    {
        Console.WriteLine("Finished: {0}", ((Process)sender).Id.ToString());
        ((Process)sender).Dispose();
        activeProcesses--;
        finishedProcesses++;
    }
}