2010-05-11 1 views
1

Comment puis-je afficher efficacement l'état d'un fichier lors de l'utilisation d'un fil d'arrière-plan?Afficher efficacement l'état du fichier lors de l'utilisation du fil d'arrière-plan

Par exemple, permet de dire que j'ai un fichier de 100 Mo:

quand je fais le code ci-dessous via un fil (comme un exemple) fonctionne dans environ 1 min:

foreach(byte b in file.bytes) 
{ 
    WriteByte(b, xxx); 
} 

Mais. .. si je veux mettre à jour l'utilisateur je dois utiliser un délégué pour mettre à jour l'interface utilisateur du thread principal, le code ci-dessous prend - FOREVER - littéralement je ne sais pas combien de temps im encore en attente, ive créé ce poste et son pas même 30% fait.

int total = file.length; 
int current = 0; 
foreach(byte b in file.bytes) 
{ 
    current++; 
    UpdateCurrentFileStatus(current, total); 
    WriteByte(b, xxx); 
} 

public delegate void UpdateCurrentFileStatus(int cur, int total); 
public void UpdateCurrentFileStatus(int cur, int total) 
{ 
     // Check if invoke required, if so create instance of delegate 
     // the update the UI 

     if(this.InvokeRequired) 
     { 

     } 
     else 
     { 
      UpdateUI(...) 
     } 
} 

Répondre

1

Je vous recommande de mettre à jour en fonction du temps écoulé pour que vous ayez des intervalles de mise à jour prévisibles quelle que soit la taille du fichier ou la charge du système:

DateTime start = DateTime.Now; 
    foreach (byte b in file.bytes) 
    { 
     if ((DateTime.Now - start).TotalMilliseconds >= 200) 
     { 
      UpdateCurrentFileStatus(current, total); 
      start = DateTime.Now; 
     } 
    } 
+0

Pour les mesures de temps relatives dans une boucle, il est préférable d'utiliser 'Stopwatch' ou même' DateTime.UtcNow', qui sont beaucoup plus rapides que 'DateTime.Now'. –

+0

Bon point. Je n'ai pas non plus réalisé que DateTime.UtcNow est plus rapide (aucune conversion de fuseau horaire). C'est toujours un plaisir d'apprendre quelque chose en répondant à autre chose! Vous pouvez également utiliser un System.Timer pour mettre à jour l'interface utilisateur, en particulier si le travail est effectué sur un autre thread. –

+0

J'aime cette approche le meilleur jusqu'à présent, merci ebpower – schmoopy

5

Ne pas mettre à jour l'interface utilisateur pour chaque octet. seulement le mettre à jour pour chaque 100k ou plus.

Observe:

int total = file.length; 
int current = 0; 
foreach(byte b in file.bytes) 
{ 
    current++; 
    if (current % 100000 == 0) 
    { 
     UpdateCurrentFileStatus(current, total); 
    } 
    WriteByte(b, xxx); 
} 
+0

très étrange, je pensais exactement cela avant de revenir à cette page - je vais donner un coup de feu et voir ... Je veux dire même tous les 1k octets ... – schmoopy

+0

Utilisez également 'Control.BeginInvoke' au lieu de 'Invoke', le thread de travail ne doit pas attendre le thread de l'interface utilisateur. –

2

Vous mettez à jour l'interface utilisateur trop souvent - chaque octet dans un fichier de 100 Mo va entraîner 100 millions de mises à jour de l'interface utilisateur (au triage thread d'interface utilisateur pour chaque). Brisez vos mises à jour en pourcentage de la taille totale du fichier, par incréments de 10% ou même de 5%. Si la taille du fichier était de 100 octets, mettez à jour l'interface utilisateur à 10, 20, 30, etc.