C# BackgroundWorker ReportProgress 行为异常
我的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
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?
显然,这个问题是在优化应用程序的可扩展性时以某种方式引入的。我终于让程序再次达到“稳定”点,重新测试,问题已经像它出现时一样神秘地消失了。
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.