2013-03-27 1 views
0

J'ai créé une application wpf. Dans mon application, j'ouvre une fenêtre et je copie en arrière-plan des fichiers. Je voudrais afficher et mettre à jour une barre de progression pendant la copie.Exception lors de la mise à jour d'une barre de progression dans une application d'arrière-plan

J'ai essayé d'utiliser un BackgroundWorker:

public partial class FenetreProgressBar : Window 
{ 

    private readonly BackgroundWorker worker = new BackgroundWorker(); 


    public FenetreProgressBar(ObservableCollection<Evenement.FichierJoint> CollectionFicJointsToAdd) 
    { 
     InitializeComponent(); 

     worker.WorkerReportsProgress = true; 
     worker.DoWork += worker_DoWork; 
     worker.RunWorkerCompleted += worker_RunWorkerCompleted; 
     worker.ProgressChanged +=worker_ProgressChanged; 

     worker.RunWorkerAsync(CollectionFicJointsToAdd); 

    } 

    private void ProgressChanged(double Persentage, ref bool Cancel) 
    { 
     if (Cancel) 
      this.Close(); 

     worker.ReportProgress((int)Persentage); 
    } 

    private void Completedelegate() 
    { 
     this.Close(); 
    } 

    private void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     ObservableCollection<Evenement.FichierJoint> collection = e.Argument as ObservableCollection<Evenement.FichierJoint>; 

     //2) On ajoute les fichiers joints à l'évènements (ce qui va donc les copier dans le répertoire paramétré) 

     foreach (Evenement.FichierJoint FichierJoint in collection) 
     { 
      if (FichierJoint.strPathFichier.Length > 0) 
      { 
       Evenement.FichierJoint monFichierJoint = new Evenement.FichierJoint(FichierJoint.strPathFichier, App.obj_myEvenement.strEvtNumeroString); 

       MaProgressBar.Minimum = 0; 
       MaProgressBar.Maximum = 100; 

       monFichierJoint.copyObject.OnProgressChanged += ProgressChanged; 
       monFichierJoint.copyObject.OnComplete += Completedelegate; 

       monFichierJoint.AddFichierJoint(); 

      } 
     } 
    } 

    private void worker_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e) 
    { 
     // Traitement terminé, on ferme la fenetre 
     this.Close(); 
    } 

    private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     MaProgressBar.Value = e.ProgressPercentage; 
    } 

} 

Lorsque le programme rendez-vous ici:

MaProgressBar.Minimum = 0; 
MaProgressBar.Maximum = 100; 

J'ai une exception: "Le thread appelant ne peut pas accéder à cet objet parce qu'un autre thread est propriétaire ".

J'ai lu plusieurs réponses sur google et stackoverflow mais je n'essaie pas d'utiliser cette approche avec BackgroundWorker.

Quelqu'un coule m'aider afin d'éviter cette exception et résoudre le problème s'il vous plaît?

Merci beaucoup,

Cordialement :)

+0

déplacer les deux instructions dans le constructeur, car vous ne pouvez pas accéder à 'MaProgressBar' à partir du thread d'arrière-plan. Une autre chose, esseye de programmeur en anglais (identificateurs), c'est mieux et le code devient plus lisible :) –

+0

Oui vous avez raison! Merci beaucoup (Merci pour l'autre conseil :)) –

Répondre

1

Vous cannot modify UI objects from background worker. Vous devez invoke les méthodes sur l'interface utilisateur dispatcher comme celui-ci -

App.Current.Dispatcher.Invoke((Action)delegate 
      { 
       MaProgressBar.Minimum = 0; 
       MaProgressBar.Maximum = 100; 
      }); 

Mais puisque vous ne devez set maximum an minimum values, je vous suggère de définir ces valeurs en dehors de BackgroundWorker dans constructor -

public FenetreProgressBar(ObservableCollection<Evenement.FichierJoint> 
         CollectionFicJointsToAdd) 
{ 
    InitializeComponent(); 

    MaProgressBar.Minimum = 0; 
    MaProgressBar.Maximum = 100; 

    worker.WorkerReportsProgress = true; 
    worker.DoWork += worker_DoWork; 
    worker.RunWorkerCompleted += worker_RunWorkerCompleted; 
    worker.ProgressChanged +=worker_ProgressChanged; 

    worker.RunWorkerAsync(CollectionFicJointsToAdd); 

} 
+0

Merci beaucoup! –

0

Pourquoi ne pas utiliser C# et nouvelle async/fonctionnalité attendre de nouveaux mots-clés? ils ont été spécialement conçus pour rendre l'interface utilisateur sensible tout en faisant de longues opérations.

+0

Vous avez raison, mais je n'utiliserais jamais async/wait :( –

0

Vous devriez essayer ceci:

_backgroundWorker.OnProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged); 

puis

// Event handler 
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    // Update main thread here 
} 
Questions connexes