从嵌套的Parallel.ForEach更新进度条

本文关键字:更新 ForEach 嵌套 Parallel | 更新日期: 2023-09-27 18:28:25

我正在重写一些代码,以使用TPL而不是BackgroundWorkers,并同时实现多线程。我的一切都运行得很好(并行运行,取消也可以),但我不知道如何适当地更新我的进度条。这就是我到目前为止所做的(由于任务很大,所以不打算写完整的任务):

更新:我已经根据一些建议对代码进行了更新。

var progressHandler = new Progress<int>(value => { pgbOverviewProgressbar.Value = value; });
progress = progressHandler as IProgress<int>;
await Task.Run(() => taskGetOverviewData(ct), ct);
public void taskGetOverviewData(CancellationToken ct)
{
    DateTime dtTime2 = DateTime.Now;
    int totalcount = lstDKCZ.Count * lstPTST.Count;
    double iCounter = 0;
    Parallel.ForEach(lstDKCZ, item =>
        {
            Parallel.ForEach(lstPTST, item2 =>
                {
                    //Lots of SQL queries and whatnot
                    double iCount = overview.Count();
                    foreach(var item3 in overview)
                    {
                        //Again lots of things happening
                        if (DateTime.Now > dtTime2.AddMilliseconds(15))
                        {
                            if (iCounter != iCount)
                                progress.Report(Convert.ToInt32((iCounter / iCount) * 100 / totalcount);
                            dtTime2 = DateTime.Now;
                        }
                    }
              }
       }
}

最多执行4次并行迭代(lstDKCZ中的2个元素和lstPTST中的2个子元素)。当按顺序进行工作时,这很好,因为progressbar只运行4次(我只希望它在整个过程中运行一次)。现在,它只是偶尔上下跳跃,但这是意料之中的,而且很容易理解原因(从4个不同的线程更新相同的变量)。

但我该如何处理呢?我在搜索答案时看到了锁定,但我不太明白如何在这种情况下实现它。

更新2:为每个场景制作4个不同的进度报告。如何合并它们?

if (DateTime.Now > dtTime2.AddMilliseconds(15))
{
    if (iCounter != iCount)
    {
        //Make 4 different of these for each scenario
        if (item == "DK" && item2 == "PT")
            progress1.Report(Convert.ToInt32((iCounter / iCount) * 100))                             
        dtTime2 = DateTime.Now;
    }
}

然后我想要的(据我所知)是这样的东西:

totalprogress = (progress1 + progress2 + progress3 + progress4) / totalcount;

不过,我似乎无法做到这一点,因为我无法将进度转换为整数并将该值传递给totalprogress。

从嵌套的Parallel.ForEach更新进度条

如果将进度除以lstDKCZ和lsPTST的长度如何?

int totalCount = lstDKCZ.Count * lstPTST.Count;
Parallel.ForEach(lstDKCZ, item =>
    {
        Parallel.ForEach(lstPTST, item2 =>
            {
                //Lots of SQL queries and whatnot
                double iCount = overview.Count();
                double iCounter = 0;
                foreach(var item3 in overview)
                {
                    //Again lots of things happening
                    if (DateTime.Now > dtTime2.AddMilliseconds(15))
                    {
                        if (iCounter != iCount)
                            progress.Report(Convert.ToInt32((iCounter / iCount) * 100 / totalCount);
                        dtTime2 = DateTime.Now;
                    }
                }
          }
   }