1

指定されたディレクトリ内のすべての 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();ことですが、一度に1つのプロセスしか実行しないため、作業全体が遅くなります:)

正確な数のプロセスを同時に実行するためにプロセス数を制限する最も簡単な方法は何ですか? ユーザーに判断してもらいたい。

一度に最大5つのプロセスを実行したいとしましょう。つまり:
- 最初の 5 つのプロセスは、ディレクトリ内の最初の 5 つのファイルに対して多かれ少なかれ同時に開始されます
- それらの 1 つ (どちらでも構いません) が作業を終了すると、次のプロセスが開始されます - 次のファイルに対して

4

2 に答える 2

1

私があなただったら、待ち行列の生産者と消費者のモデルを調べます。これはまさにこれを行うことを目的としており、ニーズに合わせて変更できる良い例がたくさんあります。

以下に例を示します: C# プロデューサー/コンシューマー

別の例: http://msdn.microsoft.com/en-us/library/hh228601%28v=vs.110%29.aspx (この最後の例は 4.5 用ですが、IMO は有効です)

于 2012-06-18T15:57:47.517 に答える
0

さて、この質問の答えを試してみましたが、奇妙なことに、それらを機能させることができませんでした。私は認めます、私は急いでいました、私はいくつかの間違いをすることができました...

今のところ、私が見つけた最も速くて単純な(そして最も醜い)メソッドは、以下のコードのように、単なるループです。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++;
    }
}
于 2012-06-25T10:00:54.963 に答える