Mon backgroundWorker
utilise ReportProgress
pour mettre à jour le ProgressPercentage
d'un processus long. Ce qui se passe est dans deux entrées sur trois ProgressChanged
ProgressPercentage
est zéro, alors que chaque troisième entrée en ProgressChanged
le ProgressPercentage
est ce que je m'attendais. Cela arrive comme sur des roulettes; c'est très reproductible. Voici un code simplifié montrant ma configuration (pour réduire la longueur, j'ai supprimé le code de gestion des erreurs):C# BackgroundWorker ReportProgress se comportant étrangement
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();
}
(Mes excuses pour la longueur, mais il a été demandé.) Le même comportement est exhibitted avec et sans le AutoResetEvent
. Quelqu'un at-il des idées sur la raison pour laquelle cela peut arriver? Merci.
DÉTAILS SUPPLÉMENTAIRES
Si je mets un point d'arrêt sur this.backgroundWorkerProgram.ReportProgress(iProgress);
, je peux voir que iProgress
incréments comme prévu (lentement, sur plusieurs intervale, par exemple 0,0,0,1,1,1,2, 2,2,3,3,3, etc.). Ensuite, si je déplace le breakpoin à string sProgressPercentage = e.ProgressPercentage.ToString() + "%";
, la valeur de e.ProgressPercentage
ne correspond pas à la valeur transmise de iProgress
. Ce que je reçois est comme 0,0,0,0,1,0,0,2,0,0,3,0,0, etc. Quelles sont les premières valeurs de iProgramSize et PIC32.ProgMem.Length?
Au lieu du pseudo-code, pourquoi ne pas nous donner un exemple court mais complet qui démontre le problème? Cela rendra beaucoup plus facile de vous aider. –
Ce comportement n'est pas normal pour un Bgw, il doit donc y avoir quelque chose dans votre code (réel). Donc je suis d'accord avec Jon: poster un petit programme de démonstration. Très probablement, vous trouverez le problème en cours de route. –
Avez-vous parcouru ce code dans le débogueur? Il semble que vous n'appelez 'ReportProgress' que dans des conditions très spécifiques. La valeur que vous passez à cette méthode ('iProgress') est également le résultat d'un calcul:' (this.iProgramSize * 100)/PIC32.ProgMem.Length', quel qu'il soit. Ce n'est pas clair pour moi en tant qu'étranger ce qui vous rendrait si sûr que cette valeur ne serait pas nulle parfois. –