2

以下のコードの問題が何であるかはわかりませんが、期待どおりに動作しません。設計は、ユーザーが ListBox から任意の数の入力ファイルを選択し、[実行] ボタンをクリックして、別の入力ファイルを使用して同じ実行可能ファイルを開始できるようにすることです。ユーザーが同時プロセスの数を指定できるようにするコントロールを追加しますが、今のところ、テストのために 3 にハードコーディングしています。私の期待は、各実行可能ファイルが順番に開始され (そのように終了しない可能性があることは理解しています)、一度に実行されるのは 3 つだけです (ただし、この数は最終的にはユーザー入力コントロールによって制御されます)。プロセスを呼び出す関数に機能を追加したいと思います。つまり、タスクの優先度、終了コードを返しますが、今のところ基本的な機能を動作させることができません。コードの多くのバリエーションを試しました。このサイトやウェブ上の他のサイトで見つけましたが、それでも動作しません。現在のバージョンは次のとおりです。

    private void btnParserExe_Click(object sender, EventArgs e)
    {
        Pool = new Semaphore(3,3);  //Pool above declared as class variable 
        string ExeName = "C:\\Program Files (x86)\\Norman\\bin\\OC2.exe";
        string Args;
        string ArgDir = this.dirListBox1.Path + "\\";

        for (int i = 0; i < this.fileListBox1.Items.Count; i++)
        {
            if (this.fileListBox1.GetSelected(i) == true)
            {
                Args = "-i " + this.fileListBox1.get_Items(i) + " -r -c -noerr";
                Thread thread = new Thread(() => DoWork(ArgDir, ExeName, Args, "3"));
                thread.Start();
            }
        }
    }


    private static void DoWork(string WorkingDir, string exefile, string parameters, string priority)
    {
        Pool.WaitOne();

        Process exeProcess = new Process();
        int exitCode;

        try
        {
            exeProcess.StartInfo.FileName = exefile;
            exeProcess.StartInfo.Arguments = parameters;
            exeProcess.StartInfo.WorkingDirectory = WorkingDir;
            exeProcess.Start();
            exeProcess.WaitForExit();
        }
        catch (Exception ex)
        {
            MessageBox.Show("ERROR EXECUTING: " + parameters + " " + ex.Message);
        }
        finally
        {
            exitCode = exeProcess.ExitCode;
        }
        Pool.Release();
    }

}

私が抱えている3つの主な問題:

  1. ジョブが常に正しい順序で開始されるとは限りません (ListBox の下位にあるいくつかの項目は、上位にある他の項目よりも前に開始されます)
  2. 開始されたプロセスが、完了したにもかかわらずウィンドウが画面に残っているかのように停止しているように見えることがあります。これはかなり一貫した問題ですが、常に同じタスク/入力ファイルが停止するわけではありません。以前のテストで問題なく機能していたものが、失速したり、逆の場合もあります。
  3. コードのこの部分のテスト中にラップトップが再起動しますか??

フィードバック、リンク、例をいただければ幸いです。

4

2 に答える 2

0
  1. There are no guarantees as to the order in which the threads will actually start up. It is very possible that two threads started (in the Thread.Start() sense) in quick succession to one another may experience the "second" one actually beginning execution before the "first one." If ordered execution is important, you will need to serialize their execution (which seems to obviate the need to start multiple threads.)

  2. I am curious if you are sure that all of your processes are starting up with the proper input file name. Your delegate usage looks to me like you could actually end up with two starting up with the same file and I'm wondering if this is contributing to your second issue.

  3. How often? Is your computer doing anything else at this time? Do you get any messages, BSOD or any form of information? This is not normal by any means.

于 2012-11-09T16:23:10.640 に答える
0

.Net 4.0 では、単純な並列タスク用の新しいツールがいくつか提供されるようになりました: http://msdn.microsoft.com/en-us/library/dd987838(v=vs.100).aspx

    string ExeName = "C:\\Program Files (x86)\\Norman\\bin\\OC2.exe";
    string Args;
    string ArgDir = "\\";

    //Simulated listbox items here:
    string[] filelist = new string[] {"file1", "file2"};

    System.Threading.Tasks.ParallelOptions options = new System.Threading.Tasks.ParallelOptions();
    options.MaxDegreeOfParallelism = 3;
    System.Threading.Tasks.Parallel.For(0, 10, options, (i => {

        Args = "-i " + filelist[i] + " -r -c -noerr";
        DoWork(ArgDir, ExeName, Args, "3");
    }
        ));
}

Parallel.For を使用すると、並行性を管理でき、タスクを順番に開始する必要があります。

.Net 2.0 では、いくつかの BackgroundWorkers と単純なコントローラー メソッドを使用できます。何かのようなもの:

Stack<string> filelist = new Stack<string>() {"file1", "file2"};

private void Setup()
{

    System.ComponentModel.BackgroundWorker backgroundWorker1;
    System.ComponentModel.BackgroundWorker backgroundWorker2;

    backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
    backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);

    backgroundWorker2.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
    backgroundWorker2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
}

private void Execute()
{
    backgroundWorker1.DoWork();
    backgroundWorker2.DoWork();
}

private string GetNextItem()
{
    //this is a crude controller
    return filelist.Pop();
}

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{   
    // Get the BackgroundWorker that raised this event.
    BackgroundWorker worker = sender as BackgroundWorker;
    string nextFile = GetNextItem();
    //Some simple check here to see if there were any items left or quit
    ....
    //Now do work
    Args = "-i " + nextFile  + " -r -c -noerr";
    DoWork(ArgDir, ExeName, Args, "3");

}

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{   
    // Check for errors...
    ...

    // See if more work to do
    if (filelist.Count > 0)
    {
        //Repeat task
        BackgroundWorker worker = sender as BackgroundWorker;
        worker.DoWork();
    }
}

BackgroundWorkers を使用すると、独立した進行状況バーなどを表示することもできます。

コードはテストされていません。

于 2012-11-09T17:24:11.213 に答える