2010-01-05 6 views
5

J'ai déjà recherché le forum mais aucune question posée ne correspond à mon problème je pense ...Pourquoi BackgroundWorker_RunWorkerCompleted ne met-il pas à jour l'interface graphique?

J'utilise un BackgroundWorker pour gérer une opération qui prend beaucoup de temps. Une fois cette opération terminée, un bouton doit être activé pour que l'utilisateur puisse effectuer une autre opération. J'utilise WPF et je suis le modèle MVVM, donc je n'ai pas d'accès direct à ce bouton. Je dois appeler une méthode dans le gestionnaire d'événements BackgroundWorker_RunWorkerCompleted qui définit une propriété, représentant les boutons enabled-state, à true.

Tout cela fonctionne bien, sauf une chose: le bouton est seulement redessiné après I par exemple. cliquez dans la fenêtre (ou agrandissez la fenêtre, ...). Cest très ennuyeux et moi avons pris toute la journée pour se débarrasser de ce comportement, mais je ne peux pas trouver une solution ...

Le gestionnaire d'événements BackgroundWorker_RunWorkerCompleted ressemble à ceci:

void fileLoadBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { 
     SetButtonToEnabled(); } 

Quelqu'un at-il une idée résoudre ce problème?

Edit:

Le bouton est lié à une commande:

<Button Name="btnLoadTargetFile" Command="{Binding Path=LoadTargetCommand}" .../> 

Cette commande est un RelayCommand comme Smith a déclaré dans son blog (http://msdn.microsoft.com/en-us/magazine/dd419663.aspx) et ressemble à ceci:

public RelayCommand LoadTargetCommand 
    { 
     get 
     { 
      if (loadTargetCommand == null) 
      { 
       loadTargetCommand = new RelayCommand(param => this.OnRequestLoadFile(BusinessLogic.CustomTypes.TreeType.Target), param => this.CanLoadTarget); 
      } 
      return loadTargetCommand; 
     } 
     set { loadTargetCommand = value; } 
    } 

this.CanLoadTarget est défini sur true par SetButtonToEnabled(); méthode

Edit 2:

le code suivant 'fonctionne':

fileLoadBackgroundWorker.RunWorkerAsync(argumentList); 
while(fileLoadBackgroundWorker.IsBusy) 
    System.Windows.Forms.Application.DoEvents(); 
SetButtonToEnabled(); 

mais qui est une sorte de code très dangereux et laid ...

+0

Lorsque vous définissez la propriété sur true, relancez-vous l'événement 'PropertyChanged' (c'est-à-dire que votre viewmodel implémente' INotifyPropertyChanged' correctement)? –

+0

Si j'appelle cette méthode après fileLoadBackgroundWorker.RunWorkerAsync() tout fonctionne bien, donc je ne pense pas que ce soit le problème ?! – lakai

+0

Juste par curiosité, utilisez-vous des modifications WMI à la forme ou à la bordure du formulaire (couleur de la bordure, etc.)? –

Répondre

2

Althought il ne marche pas expliquer votre problème, vous pouvez essayer d'ajouter

System.Windows.Forms.Application.DoEvents(); 

ou

Dispatcher.Invoke(new Action(delegate { }), DispatcherPriority.Background); 

à la fin de votre appel de fonction SetButtonToEnabled (après avoir défini le bouton Activé true). Il semble que l'arrière-plan appelle l'événement Complete, mais l'interface graphique n'est pas rafraîchissante.

Here est un exemple complet utilisant l'arrière-plan dans WPF. Vous voudrez peut-être y jeter un coup d'œil et vous assurer que vos affaires sont identiques.Vous pouvez également jeter un oeil à Asynchronous Threading with Background Worker Object. Ceci est un bon exemple d'utilisation de Dispatcher et de l'arrière-plan

La WPF Threading Model est une autre excellente source à consulter.

+0

merci pour votre commentaire! mon code ressemble à l'exemple sauf que je n'ai pas d'accès direct aux boutons à cause du modèle MVVM que j'utilise – lakai

+0

Pourriez-vous poster le code pour SetButtonToEnabled. Je ne pense pas que c'est un problème avec backgroundworker, puisque vous avez mentionné que Complete est appelé. C'est probablement quelque chose que vous faites sur le fil principal. Que faites-vous pendant que le processus fonctionne en arrière-plan? – SwDevMan81

+1

Vous pourriez vouloir vérifier InvalidateRequerySuggested: http://msdn.microsoft.com/en-us/library/system.windows.input.commandmanager.invalidaterequerysuggested.aspx Essayez d'ajouter ceci à la fin de SetButtonToEnabled – SwDevMan81

1

Votre problème n'a probablement rien à faire avec BackgroundWorker. Si vous appelez la méthode SetButtonToEnabled directement à partir du thread principal, vous verrez probablement le même comportement. Remplacer l'appel à RunWorkerAsync avec un à SetButtonToEnabled pour le tester. Un couple de commentateurs a suggéré que vous regardiez votre implémentation INotifyPropertyChanged cela ressemble à un bon conseil.

+0

merci pour votre réponse! Si j'appelle SetButtonToEnabled dans le thread principal tout fonctionne bien ... – lakai

+0

Pouvez-vous confirmer que l'événement RunWorkerCompleted est levé? Est-ce qu'un point d'arrêt que vous définissez là est touché? –

+0

oui c'est le cas, breakpoint est touché – lakai

Questions connexes