2010-05-31 2 views
1

J'ai la méthode ci-dessous qui semble se comporter bizarrement. Les ProgressChanged et RunWorkerCompleted semblent se mettre à jour en même temps. Si je commente le code RunWorkerCompleted qui met à jour le bloc de texte, je vois le ProgressChanged prendre effet après le transfert des données. Qu'est-ce que je fais mal ici? Je veux évidemment que le bloc de texte montre que je reçois des données, puis change quand j'ai fini d'obtenir les données.WPF BackGroundWorker ProgressChanged ne pas mettre à jour le bloc de texte

public void GetAppointmentsBackground() 
{ 
    System.Windows.Threading.Dispatcher webServiceDispatcher = this.Dispatcher; 
    worker = new BackgroundWorker(); 
    worker.WorkerReportsProgress = true; 
    worker.DoWork += delegate(object sender, DoWorkEventArgs args) 
    { 
    GetAppointmentsForDayDelegate getAppt = new GetAppointmentsForDayDelegate(GetAppointmentsForDay); 
    webServiceDispatcher.BeginInvoke(getAppt); 
    (sender as BackgroundWorker).ReportProgress(25); 
    }; 

    worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args) 
    { 
    txtMessages.Text = "Contacting Server"; 
    }; 

    worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
    { 
    txtMessages.Text = "Completed Successfully"; 
    }; 

    worker.RunWorkerAsync(); 
} 

Répondre

0

Je vous suggère envelopper cela dans un bloc try{...}catch ... et une clause using, comme indiqué ci-dessous

 
public void GetAppointmentsBackground() 
{ 
    System.Windows.Threading.Dispatcher webServiceDispatcher = this.Dispatcher; 
    try 
    { 
    using (BackgroundWorker worker = new BackgroundWorker()) 
    { 
     worker.WorkerReportsProgress = true; 
     worker.DoWork += delegate(object sender, DoWorkEventArgs args) 
     { 
      GetAppointmentsForDayDelegate getAppt = new GetAppointmentsForDayDelegate(GetAppointmentsForDay); 
      webServiceDispatcher.BeginInvoke(getAppt); 
      (sender as BackgroundWorker).ReportProgress(25); 
     }; 

     worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args) 
     { 
      txtMessages.Text = "Contacting Server"; 
     }; 

     worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
     { 
      if (txtMessages.InvokeRequired) 
      { 
      txtMessages.BeginInvoke(new MethodInvoker(delegate() 
      { 
       txtMessages.Text = "Completed Successfully"; 
      })); 
      } 
      else 
      { 
      txtMessages.Text = "Completed Successfully"; 
      } 
     }; 

     worker.RunWorkerAsync(); 
    } 
    } 
    catch(Exception eX) 
    { 
     /* CHECK HERE TO SEE IF AN EXCEPTION IS THROWN */ 
    } 
} 

S'il n'y a pas exception levée, en utilisant peut-être une méthode BeginInvoke du txtMessages comme indiqué ci-dessus dans le gestionnaire d'événements RunWorkerCompleted, car il peut y avoir une erreur d'inter-threading lors de la tentative de mise à jour de txtMessages lui-même à partir de la classe backgroundworker.

+0

J'ai essayé cela et aucune exception n'est levée. Incidemment, je ne vois pas le "InvokeRequired" comme une propriété de la classe TextBlock. Après être resté debout toute la nuit là-dessus, je pense que je ferais mieux d'utiliser des répartiteurs directs et de les invoquer pour que je puisse avoir une vie. –

1

En fait, le fait est qu'un autre modèle est utilisé pour System.Windows.Controls (diffère de Windows.Forms.Control descendants). Je utilisé quelque chose comme:

public delegate void NoArgs(); 

//... 

txtBlock.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, 
    new NoArgs(UpdateTextBlock)); 

//... 

void UpdateTextBlock() 
{ 
    txtBlock.Text = "Contacting Server"; 
} 

Lisez le manuel sur les Dispatcher et DispatcherObject à cet effet.

Questions connexes