在.NET 4.5中并行运行.exe进程并更新进度条

3
我有一个dataGridView,在其中为每个条目运行一个进程,然后根据进程的输出更新toolStripProgressBar。
我查看了以下线程, 在.NET 4.5中并行运行两个异步任务并收集结果 并行循环调用中的进度条 如何从同时运行的任务更新进度条 但我不知道如何将我的当前代码更改为类似这些线程的代码。 我认为,与这些线程的主要区别在于,我的计算是由外部应用程序完成的,然后我需要收集输出。 我想我必须将每个进程定义为一个异步任务,然后以某种方式收集输出。
为简单起见,在示例代码中,处理过程具有相等的权重。
private iNumProcesses; 
private void RunApps()
{
    iNumProcesses = dataGridView1.Rows.Count;
    string sPath = .exe application path    
    for (int i = 0; i < iNumProcesses; i++)
    {   
        string sArgs = dataGridView1.Rows[i]["Arguments"].ToString();
        ExecuteProgram(sPath, sArgs);
    }
}
private void ExecuteProgram(string sProcessName, string sArgs) 
{
    using (cmd = new Process())
    {
        cmd.StartInfo.FileName = sProcessName;
        cmd.StartInfo.Arguments = sArgs;
        cmd.StartInfo.UseShellExecute = false;
        cmd.StartInfo.CreateNoWindow = true;
        cmd.StartInfo.ErrorDialog = true;
        cmd.StartInfo.RedirectStandardOutput = true;
        cmd.StartInfo.RedirectStandardError = true;
        cmd.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler);
        cmd.ErrorDataReceived += new DataReceivedEventHandler(SortOutputHandler);
        cmd.Start();
        cmd.BeginOutputReadLine();
        while (!cmd.HasExited) { Application.DoEvents(); }
    }        
}
private void SortOutputHandler(object sender, DataReceivedEventArgs e)
{
    Trace.WriteLine(e.Data);
    this.BeginInvoke(new MethodInvoker(() =>
    {
        if (e.Data == "Start") { do something... }
        else if (e.Data == "Finish") { do something... }
        else if (e.Data == "End")   { do something... }
        else
        {
            // .exe application output numbers 1 through 100
            toolStripProgressBar1.Value += Math.Round(Convert.ToInt32(e.Data)/iNumProcesses,0);
        }
    }));
}

我该如何并行运行进程并根据从.exe应用程序获得的1到100的输出数字更新进度条?欢迎任何建议或建议。
1个回答

0

我对这个问题的答案并不特别与"C#"相关,因此我不会直接用那些术语来表述:这个令人意外地棘手的问题实际上是普遍存在的。

  • 你必须做的第一件事是安排定期更新用户显示。为了避免不良竞争条件和其他问题,你应该让“主线程”通过毫秒计时器执行此任务。该线程查询共享的进度信息数组,并相应地更新所有进度条。(如果你想使用事件来避免直接的“定时等待”,请随意这样做。)

  • 由于每个启动的子进程都有自己的输入和输出流,并且将异步写入这些流,因此你需要在应用程序中生成一个“母线程”来监督每个子进程。该线程对应于特定的外部进程,实际上是启动它的线程。该线程将继续存在,直到确定它启动的进程已死亡。

  • “母线程”观察其指定的子进程的输出流以确定其“进度”。它相应地更新共享数组中的进度变量。(该设计的关键要素是每个“母线程”能够将100%的注意力仅集中在它的子进程上。并且,因为所有的“母亲们”都是线程,它们可以轻松地与更新这些进度条的线程共享信息。)

  • 你是否实际上必须使用信号量等来协调母线程和主线程之间的访问?当然,这取决于该数据结构的确切内部实现,答案可能是“可能不需要。”(哦,但最好还是这样做。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接