2017-10-09 5 views
0

J'ai lu tant d'articles et d'autres questions sur ce sujet, mais parce que je suis très nouveau à C# et travailler avec des discussions en général, les réponses étaient malheureusement trop compliquées pour moi et mon problème.Mettre à jour la barre de progression dans un autre fil

J'ai cette barre de progression qui sera remplie avec de très petits pas, généralement 0,03%. En incluant ceci normalement, il est passé de 0 à 100 dans un instand à la fin de l'opération, mais je l'ai parcouru à chaque fois et je le mets à jour à raison de 0,03% à chaque fois. Je crois que la mise à jour de la barre de progression dans un autre thread fera l'affaire, mais malheureusement je n'ai aucune compréhension de ce sujet à ce jour.

C'est la section de code où ma barre de progression sera mise à jour:

public void CopyAll(DirectoryInfo source, DirectoryInfo target) 
{ 
    string source4count = source.ToString(); 
    if (checkSubdirCase == 0) 
    { 
     allfiles = System.IO.Directory.GetFiles(source4count, "*.*", System.IO.SearchOption.AllDirectories); 
     allFilesNum = allfiles.Length; 
     progressbarinterval = 0;      
     progressbarinterval = 100/allFilesNum; 
     Progressbarvalue = 0; 
    } 

    if (Directory.Exists(target.FullName) == false) 
    { 
     Directory.CreateDirectory(target.FullName); 
    } 

    foreach (FileInfo fi in source.GetFiles()) 
    { 
     //HERE IS THE UPDATING OF THE PROGRESSBAR 
     fi.CopyTo(System.IO.Path.Combine(target.ToString(), fi.Name), true); 
     Progressbarvalue = Progressbarvalue + progressbarinterval;      
     ProgressBarCopy.Value = Progressbarvalue; 
    } 
    foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) 
    { 
     DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name); 
     checkSubdirCase = 1; 
     CopyAll(diSourceSubDir, nextTargetSubDir); 
    } 
} 

J'espère que someeone peut me aider et expliquer de façon simple comment aborder ce sujet et comment les travailleurs de fond fonctionnent réellement. Cordialement

Répondre

2

Vous voulez probablement créer un travailleur de fond (ce qui se passe sur le thread d'interface utilisateur) comme ceci:

var worker = new BackgroundWorker(); 
worker.WorkerReportsProgress = true; 
worker.DoWork += new DoWorkEventHandler(WorkerDoWork); 
worker.ProgressChanged += new ProgressChangedEventHandler(WorkerProgressChanged); 

Dans votre DoWork méthode, vous ferez tout ce que vous faites actuellement dans le CopyAll -method, seule la gestion de la progression va changer. Vous devez appeler worker.ReportProgress (...), cela retournera dans le thread UI et appellera votre méthode WorkerProgressChanged. Dans la méthode WorkerProgressChanged, vous pouvez mettre à jour votre barre de progression. Cependant, vous devez être conscient du fait que la commutation entre le thread de l'interface utilisateur et votre thread BackgroundWorker est plutôt coûteuse, vous ne devriez donc signaler la progression que lorsqu'elle a réellement changé d'une certaine manière sur l'interface utilisateur.

+2

Merci pour cette réponse. C'était facilement compréhensible et je vais l'essayer maintenant. :) – MansNotHot

2

Une autre solution est l'utilisation d'une tâche avec un Invoke sur la barre de progression

Modifier le code sur votre bouton

//CopyAll(); //Old 
Task.Run(() => CopyAll()); 

Votre méthode avec un Invoke

public void CopyAll(DirectoryInfo source, DirectoryInfo target) 
{ 
    string source4count = source.ToString(); 
    if (checkSubdirCase == 0) 
    { 
     allfiles = System.IO.Directory.GetFiles(source4count, "*.*", System.IO.SearchOption.AllDirectories); 
     allFilesNum = allfiles.Length; 
     progressbarinterval = 0;      
     progressbarinterval = 100/allFilesNum; 
     Progressbarvalue = 0; 
    } 

    if (Directory.Exists(target.FullName) == false) 
    { 
     Directory.CreateDirectory(target.FullName); 
    } 

    foreach (FileInfo fi in source.GetFiles()) 
    { 
     //HERE IS THE UPDATING OF THE PROGRESSBAR 
     fi.CopyTo(System.IO.Path.Combine(target.ToString(), fi.Name), true); 
     Progressbarvalue = Progressbarvalue + progressbarinterval;      
     ProgressBarCopy.Invoke(new MethodInvoker(delegate { ProgressBarCopy.Value = Progressbarvalue; })); 
    } 
    foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) 
    { 
     DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name); 
     checkSubdirCase = 1; 
     CopyAll(diSourceSubDir, nextTargetSubDir); 
    } 
} 
+0

Je suis confus avec le Task.run (() -> CopyAll(); Où devrait-il être mis et qu'est-ce qu'il fait? UPATE: Je l'ai eu. Ma barre de progression devEx ne semble pas avoir "invoquer" mais je vais changer pour standart barre de progression et voir – MansNotHot

+0

Encore obtenir le message d'erreur: barre de progression ne contient pas une définition pour invoke.Je ne sais pas quel est le problème .. – MansNotHot

+0

MISE À JOUR: trouvé. – MansNotHot

1

Utilisation de la Background Worker est une bonne option.

var worker = new BackgroundWorker(); 
worker.DoWork += new DoWorkEventHandler(Worker_DoWork); 
worker.ProgressChanged += new 
ProgressChangedEventHandler(Worker_ProgressChanged); 
worker.RunWorkerCompleted += new 
RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted); 


private void Worker_DoWork(object sender, DoWorkEventArgs e) 
{ 

... 
    foreach (FileInfo fi in source.GetFiles()) 
    { 
    //Copying the files.. 

    // Calling the ReportProgress method would fire the worker_ProgressChanged event 
    worker.ReportProgress(0, progressState) 
} 


    } 

    private void worker_ProgressChanged(object sender, 
             ProgressChangedEventArgs e) 
    { 
     // This is where you would have the UI related changes. 
     //In your case updating the progressbar. 
     // While the files are being copied this would update the UI. 
    } 

private void Worker_RunWorkerCompleted(object sender, 
RunWorkerCompletedEventArgs e) 
{ 
worker.CancelAsync(); 

}