0

J'ai une application dans laquelle l'utilisateur peut démarrer des tâches, tâches lourdes. Et je veux gérer la progression de ces tâches dans une grille d'interface utilisateur (chaque ligne est une tâche, avec une barre de progression) l'utilisateur peut afficher cette grille en cliquant sur un bouton (en utilisant le fil principal). Le problème que j'ai est Thread Thread Operation. Je sais pourquoi: à chaque fois que la progression de la tâche a changé (avec thread1), l'algorithme essaie de mettre à jour la source de données de la grille (avec le thread principal). Mais je ne sais pas comment le réparer.Gérer les progressions de tâches dans une interface utilisateur

La propriété DataSource de ma grille est définie sur BindingList<BackgroundOperation>.

La définition de ma tâche (BackgroundOperation)

public class BackgroundOperation 
{ 
    public int progression; 
    public int Progression 
    { 
     get { return progression;} 
     set 
     { 
      progression = value; 
      OnPropertyChanged("Progression"); 
     } 
    } 

    public event EventHandler OnRun; 
    public event EventHandler<ProgressChangedEventArgs> OnProgressChanged; 
    public event PropertyChangedEventHandler PropertyChanged; 

    public void Run() 
    { 
     var task = new Task(() => 
     { 
      if (OnRun != null) 
       OnRun(this, null); 
     }); 

    task.Start(); 
    } 

    public void ReportProgress(int progression) 
    { 
     Progression = progression; 

     if (OnProgressChanged != null) 
      OnProgressChanged(this, new ProgressChangedEventArgs { Progression = progression }); 
    } 


    protected void OnPropertyChanged(string name) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 
+0

Avez-vous accès à .NET4.0 ou même .NET4.5 +? Vous n'utilisez pas TPL ici, bien que je suggère que vous le fassiez ... – MoonKnight

+1

vous voulez que le thread principal et le thread principal seulement pour gérer l'interface utilisateur. Cela signifie que vous devez trouver un moyen pour thread1 de signaler un changement sur une progression donnée, et principal pour attraper ce signal et mettre à jour l'affichage. Une technique habituelle consiste à avoir une file d'attente d'événements, à laquelle chaque thread va produire/consommer. – didierc

Répondre

2

Vous devez exécuter le OnProgressChanged (qui devrait être appelé juste BTW ProgressChanged) sur le thread d'interface utilisateur. Vous pouvez le faire en sauvant the current SynchronizationContext lorsque la classe est créée puis le délégué Post() ing il:

public class BackgroundOperation 
{ 
    private readonly SynchronizationContext m_synchronizationContext; 

    public BackgroundOperation() 
    { 
     m_synchronizationContext = SynchronizationContext.Current; 
    } 

    … 

    public void ReportProgress(int progression) 
    { 
     Progression = progression; 

     var handler = OnProgressChanged; 
     if (handler != null) 
      m_synchronizationContext.Post(
       _ => handler(
        this, 
        new ProgressChangedEventArgs { Progression = progression }), 
       null); 
    } 
} 
+0

Cela fonctionne comme il se doit. Merci beaucoup pour votre aide. (+1 pour la classe SynchronizationContext). – SidAhmed

Questions connexes