C# BackgroundWorker ReportProgress 行为异常

发布于 2024-09-09 03:05:49 字数 4034 浏览 2 评论 0原文

我的 backgroundWorker 使用 ReportProgress 来更新长进程的 ProgressPercentage。发生的情况是 ProgressChanged ProgressPercentage 的三个条目中有两个为零,而 ProgressChanged 中每三个条目的 ProgressPercentage 都是零。 > 是我所期望的。这就像发条一样发生。它是非常可重复的。这是一些演示我的设置的简化代码(为了减少长度,我删除了错误处理代码):(

AutoResetEvent areProgressChanged = new AutoResetEvent(false);

  private void backgroundWorkerProgram_DoWork(object sender, DoWorkEventArgs e)
  {
     bool bRetVal = true;
     int iRetries = 3;
     int iProgress = 0;

     // Repeat Program message and entire sequence until programming
     // is complete or Retries reaches 0...
     do
     {
        bRetVal = Program();

        this.eBgwProgramStatus = BgwProgramStatus.BUSY;
        bRetVal = this.WaitForReceive(SHORT_ACK_WAIT, backgroundWorkerProgram);

        switch (this.eCommsRsp)
        {
           case CommsRsp.ACK:
              this.eBgwProgramStatus = BgwProgramStatus.BUSY;
              iRetries = 3;
              break;
        }
     }
     while ((!backgroundWorkerProgram.CancellationPending)
        && (!bRetVal) && (iRetries > 0));

     // Repeat Write and Data message until programming is complete...
     do
     {
        this.eBgwProgramStatus = BgwProgramStatus.BUSY;
        bRetVal = Write();

        this.eBgwProgramStatus = BgwProgramStatus.BUSY;
        bRetVal = this.WaitForReceive(SHORT_ACK_WAIT, backgroundWorkerProgram);

        switch (this.eCommsRsp)
        {
           case CommsRsp.ACK:
              this.eBgwProgramStatus = BgwProgramStatus.BUSY;
              bRetVal = SendData(pData_c);
              break;

           default:
           case CommsRsp.NACK:
           case CommsRsp.NONE:
              this.eBgwProgramStatus = BgwProgramStatus.NO_ACK_RXD;
              iRetries--;
              bRetVal = false;
              break;
        }

        this.eBgwProgramStatus = BgwProgramStatus.BUSY;
        bRetVal = this.WaitForReceive(SHORT_ACK_WAIT, backgroundWorkerProgram);

        switch (this.eCommsRsp)
        {
           case CommsRsp.ACK:
              this.eBgwProgramStatus = BgwProgramStatus.BUSY;
              iProgress = (this.iProgramSize * 100) / PIC32.ProgMem.Length;
              this.backgroundWorkerProgram.ReportProgress(iProgress);
              this.areProgressChanged.WaitOne();
              iRetries = 3;
              this.iRow++;
              break;

           default:
           case CommsRsp.NACK:
           case CommsRsp.NONE:
              this.eBgwProgramStatus = BgwProgramStatus.NO_ACK_RXD;
              iRetries--;
              bRetVal = false;
              break;
        }
     }
     while ((!backgroundWorkerProgram.CancellationPending)
        && (iRetries > 0)
        && ((!bRetVal) || (this.eBgwProgramStatus == BgwProgramStatus.BUSY)));
  }

  private void backgroundWorkerProgram_ProgressChanged(object sender, ProgressChangedEventArgs e)
  {
     string sProgressPercentage = e.ProgressPercentage.ToString() + "%";

     // Report progress.
     this.labelPercentComplete.Visible = true;
     this.labelPercentComplete.Text = sProgressPercentage;
     this.toolStripStatusLabel.Text = this.sProgramming + sProgressPercentage;
     this.textBoxData.AppendText(this.tBusText.ToString());
     this.textBoxStatus.AppendText(this.tStatusText.ToString());
     this.tBusText.Remove(0, this.tBusText.Length);
     this.tStatusText.Remove(0, this.tStatusText.Length);
     this.areProgressChanged.Set();
  }

我对长度表示歉意,但这是要求的。)使用和不使用 都会表现出相同的行为自动重置事件。有谁知道为什么会发生这种情况?谢谢。

其他详细信息

如果我在 this.backgroundWorkerProgram.ReportProgress(iProgress); 上设置断点,我可以看到 iProgress 按预期递增(缓慢地,多个区间,例如 0,0,0,1,1,1,2,2,2,3,3,3 等)。然后,如果我将断点移动到 string sProgressPercentage = e.ProgressPercentage.ToString() + "%";,则 e.ProgressPercentage 的值与传递的值不匹配iProgress。我得到的是 0,0,0,0,1,0,0,2,0,0,3,0,0 等。

My backgroundWorker uses ReportProgress to update the ProgressPercentage of a long process. What happens is in two out of three entries into ProgressChanged ProgressPercentage is zero, whereas every third entry into ProgressChanged the ProgressPercentage is what I would expect. This happens like clockwork; it is very repeatable. Here is some simplified code demonstrating my setup (to reduce the length, I've removed the error-handling code):

AutoResetEvent areProgressChanged = new AutoResetEvent(false);

  private void backgroundWorkerProgram_DoWork(object sender, DoWorkEventArgs e)
  {
     bool bRetVal = true;
     int iRetries = 3;
     int iProgress = 0;

     // Repeat Program message and entire sequence until programming
     // is complete or Retries reaches 0...
     do
     {
        bRetVal = Program();

        this.eBgwProgramStatus = BgwProgramStatus.BUSY;
        bRetVal = this.WaitForReceive(SHORT_ACK_WAIT, backgroundWorkerProgram);

        switch (this.eCommsRsp)
        {
           case CommsRsp.ACK:
              this.eBgwProgramStatus = BgwProgramStatus.BUSY;
              iRetries = 3;
              break;
        }
     }
     while ((!backgroundWorkerProgram.CancellationPending)
        && (!bRetVal) && (iRetries > 0));

     // Repeat Write and Data message until programming is complete...
     do
     {
        this.eBgwProgramStatus = BgwProgramStatus.BUSY;
        bRetVal = Write();

        this.eBgwProgramStatus = BgwProgramStatus.BUSY;
        bRetVal = this.WaitForReceive(SHORT_ACK_WAIT, backgroundWorkerProgram);

        switch (this.eCommsRsp)
        {
           case CommsRsp.ACK:
              this.eBgwProgramStatus = BgwProgramStatus.BUSY;
              bRetVal = SendData(pData_c);
              break;

           default:
           case CommsRsp.NACK:
           case CommsRsp.NONE:
              this.eBgwProgramStatus = BgwProgramStatus.NO_ACK_RXD;
              iRetries--;
              bRetVal = false;
              break;
        }

        this.eBgwProgramStatus = BgwProgramStatus.BUSY;
        bRetVal = this.WaitForReceive(SHORT_ACK_WAIT, backgroundWorkerProgram);

        switch (this.eCommsRsp)
        {
           case CommsRsp.ACK:
              this.eBgwProgramStatus = BgwProgramStatus.BUSY;
              iProgress = (this.iProgramSize * 100) / PIC32.ProgMem.Length;
              this.backgroundWorkerProgram.ReportProgress(iProgress);
              this.areProgressChanged.WaitOne();
              iRetries = 3;
              this.iRow++;
              break;

           default:
           case CommsRsp.NACK:
           case CommsRsp.NONE:
              this.eBgwProgramStatus = BgwProgramStatus.NO_ACK_RXD;
              iRetries--;
              bRetVal = false;
              break;
        }
     }
     while ((!backgroundWorkerProgram.CancellationPending)
        && (iRetries > 0)
        && ((!bRetVal) || (this.eBgwProgramStatus == BgwProgramStatus.BUSY)));
  }

  private void backgroundWorkerProgram_ProgressChanged(object sender, ProgressChangedEventArgs e)
  {
     string sProgressPercentage = e.ProgressPercentage.ToString() + "%";

     // Report progress.
     this.labelPercentComplete.Visible = true;
     this.labelPercentComplete.Text = sProgressPercentage;
     this.toolStripStatusLabel.Text = this.sProgramming + sProgressPercentage;
     this.textBoxData.AppendText(this.tBusText.ToString());
     this.textBoxStatus.AppendText(this.tStatusText.ToString());
     this.tBusText.Remove(0, this.tBusText.Length);
     this.tStatusText.Remove(0, this.tStatusText.Length);
     this.areProgressChanged.Set();
  }

(My apologies for the length, but it was requested.) The same behavior is exhibitted with and without the AutoResetEvent. Does anyone have any thoughts as to why this may be happenning? Thanks.

ADDITIONAL DETAILS

If I set a breakpoint on this.backgroundWorkerProgram.ReportProgress(iProgress);, I can see that iProgress increments as expected (slowly, over several intervale, e.g. 0,0,0,1,1,1,2,2,2,3,3,3,etc.). Then, if I move the breakpoin to string sProgressPercentage = e.ProgressPercentage.ToString() + "%";, the value of e.ProgressPercentage does not match the passed value of iProgress. What I get is like 0,0,0,0,1,0,0,2,0,0,3,0,0,etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

橘虞初梦 2024-09-16 03:05:49

iProgramSize 和 PIC32.ProgMem.Length 的前几个值是什么?

例如,如果 PIC32.ProgramMem.Length 为 300,iProgramSize 为 1,2,3,4,5,6 等,那么完成的百分比应为 0,0,1,1,1,2 等。

另外,您是确保 ProgressPercentage 传递错误,是否可能是标签控件未正确更新/刷新?

What are the first few values of iProgramSize and PIC32.ProgMem.Length ?

For example if PIC32.ProgramMem.Length was 300, and iProgramSize was 1,2,3,4,5,6 etc, then the percentages complete should be 0,0,1,1,1,2 etc.

Also, are you sure the ProgressPercentage is passed incorrectly, could be it that the label control not be updated/refreshed correctly?

混吃等死 2024-09-16 03:05:49

显然,这个问题是在优化应用程序的可扩展性时以某种方式引入的。我终于让程序再次达到“稳定”点,重新测试,问题已经像它出现时一样神秘地消失了。

Apparently, this problem was somehow introduced while optimizing the application for scalability. I finally got the program to a "stable" point again, retested, and the problem has gone away just as mysteriously as it appeared.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文