2016-06-28 2 views
0

J'ai un problème que j'ai écrit une application qui parcourrait les fichiers et ajouter +1 à l'entier chaque fichier, jusqu'à ce qu'il atteigne un nom de fichier spécifique. Le problème est probablement dû au fait que .Net n'accède pas directement au système de fichiers natif, il remplit les collections, mais dans mon cas cela prendrait des années, croyez-moi, j'ai 260 000 fichiers dans le dossier cible. L'itération n'atteint même pas le deuxième fichier. Le fil se fige totalement, pas d'erreurs, pas d'exceptions. Alors, y a-t-il un moyen d'obtenir un accès direct au système de fichiers natif sans aucun remplissage de collection inutile?C# .Net Freeze en itérant à travers un grand nombre de fichiers

Voici mon code:

private void button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     foreach (string file in Directory.GetFiles("\\\\Mypcname-PC\\vxheaven\\malware")) 
     { 
      count++; 
      label1.Text = Convert.ToString(count); 
      if (file.Contains(textBox1.Text)) 
      { 
       label1.Text = Convert.ToString(count) + " reached the file"; 
       break; 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 

btw. Désolé pour mon mauvais anglais

Cordialement

+3

Si vous voulez que nous vous aidions avec votre code, vous devez montrer votre code. [Modifier votre question] (http://stackoverflow.com/posts/38083668/edit) et inclure le code qui itère les fichiers. –

+0

Cela ressemble à un problème dans le code s'il n'atteint jamais le second élément. Peut-être parce qu'il semble que vous modifiez la collection – Plutonix

+0

Désolé d'avoir oublié que j'utilise Directory.GetFiles() – Yogibear

Répondre

10

Parce que vous faites tout le travail sur le thread d'interface utilisateur, il ne peut pas rafraîchir pendant qu'il fonctionne. Vous devez effectuer le travail sur un thread d'arrière-plan, puis mettre à jour l'interface utilisateur d'une manière sûre pour les threads. En passant également au Directory.EnumerateFiles, il sera plus rapide de lire le premier fichier de sorte qu'il n'a pas besoin de stocker tous les enregistrements dans un tableau. Enfin j'ai changé ex.Message à ex.ToString(), il affichera beaucoup plus d'informations utiles de cette façon.

private async void button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     var text = textBox1.Text; 
     var progress = new Progress<string>((x) => label1.Text = x); 
     await Task.Run(() => DoWork(progress, text)); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.ToString()); 
    } 
} 

private void DoWork(IProgress<string> progress, string text) 
{ 
    foreach (string file in Directory.EnumerateFiles("\\\\Mypcname-PC\\vxheaven\\malware")) 
    { 
     count++; 
     progress.Report(Convert.ToString(count)); 
     if (file.Contains(text)) 
     { 
      progress.Report(Convert.ToString(count) + " reached the file"); 
      break; 
     } 
    } 
} 

(code a été écrit dans un navigateur Web à partir de la mémoire donc il peut y avoir des erreurs)

+0

Pensé à ce sujet, mais je ne pensais pas que ce serait le problème, je vais vérifier cela – Yogibear

+2

La raison pour laquelle il semble que ça ne fonctionne pas parce que vous bloquez l'interface utilisateur, il fonctionne, mais il peut tout simplement ' t vous dire que cela fonctionne –

+0

Bon, copié dans le projet, la seule question est, quelles références supplémentaires dois-je inclure? – Yogibear

-1

On dirait que vous utilisez une boucle de temps potentiellement très sans jamais le traitement de la file d'attente de messages Windows, donc votre application peut sembler être gelé, alors qu'il est probablement juste occupé à faire ce que vous lui avez demandé de faire dans la boucle. Essayez ceci:

private void button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     foreach (string file in Directory.GetFiles("\\\\Mypcname-PC\\vxheaven\\malware")) 
     { 
      count++; 
      label1.Text = Convert.ToString(count); 
      Application.DoEvents(); 
      if (file.Contains(textBox1.Text)) 
      { 
       label1.Text = Convert.ToString(count) + " reached the file"; 
       break; 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 
+1

'Application.DoEvents();' est très dangereux à faire, vous pouvez bousiller le état interne de votre programme si vous ne faites pas attention. Vous ne devriez pas l'utiliser comme premier choix d'options. –

+0

Ce fut une solution rapide et sale sans changer son code d'origine. Bien sûr, votre code est beaucoup mieux (votant votre réponse) mais c'est une réécriture complète, pas une solution. ;) – FjodrSo