2010-07-14 4 views
0

Mon backgroundWorker utilise ReportProgress pour mettre à jour le ProgressPercentage d'un processus long. Ce qui se passe est dans deux entrées sur trois ProgressChangedProgressPercentage 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?

+4

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. –

+0

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. –

+0

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. –

Répondre

0

Apparemment, ce problème a été introduit d'une manière ou d'une autre tout en optimisant l'application pour l'évolutivité. J'ai finalement remis le programme à un point "stable", retesté, et le problème a disparu aussi mystérieusement qu'il est apparu.

1

Par exemple si PIC32.ProgramMem.Length était 300, et iProgramSize était 1,2,3,4,5,6 etc, alors les pourcentages complets devraient être 0,0,1,1,1,2 etc.

Également, êtes-vous sûr que le ProgressPercentage est transmis de manière incorrecte, peut-être que le contrôle d'étiquette n'est pas mis à jour/actualisé correctement?

+0

'iProgramSize' commence par 0 et augmente jusqu'à' PIC32.ProgramMem.Length', qui est une valeur fixe dans cette partie de l'application d'environ 512K. Si je définis un point d'arrêt sur 'this.backgroundWorkerProgram.ReportProgress (iProgress);', je peux voir que 'iProgress' s'incrémente comme prévu (lentement, sur plusieurs intervales, par exemple 0,0,0,1,1,1,2 2,2,3,3,3, etc.). Ensuite, si je déplace le breakpoin vers 'string sProgressPercentage = e.ProgressPercentage.ToString() +"% ";', la valeur de e.ProgressPercentage ne correspond pas à la valeur passée de 'iProgress'. Ce que je reçois est comme 0,0,0,0,1,0,0,2,0,0,3,0,0, etc. –

+0

Étrange. Je suppose que le e.ProgressPercentage se termine avec des valeurs comme 98,0,0,99,0,0,100 et une solution de contournement ne consisterait probablement pas à mettre à jour les étiquettes si e.ProgressPercentage est égal à zéro. Le nombre de valeurs incorrectes (zéros) liées au nombre d'entrées répétées, c'est-à-dire si vous changez votre iProgress pour être = (this.iProgramSize * 50)/PIC32.ProgMem.Length cela signifie-t-il que vous avez plus de zéros? entre les valeurs correctes? – sgmoore

+0

Apparemment, ce problème a été introduit d'une manière ou d'une autre tout en optimisant l'application pour l'évolutivité. J'ai finalement remis le programme à un point "stable", retesté, et le problème a disparu aussi mystérieusement qu'il est apparu. J'ai voté pour votre réponse parce que vous avez réfléchi de façon critique à ma question, essayé d'aider et que vous ne l'avez pas simplement rejeté. Gloire! –

Questions connexes