2016-06-28 44 views
0

我遇到了一個問題,那就是我編寫了一個應用程序,該應用程序會遍歷文件並將+1加到每個文件的整數中,直到達到特定文件名。問題可能是因爲.Net不直接訪問本地文件系統,它填滿了集合,但在我的情況下,需要幾年,相信我,目標文件夾中有260 000個文件。迭代甚至沒有達到第二個文件。線程完全凍結,沒有錯誤,沒有例外。那麼有沒有什麼辦法可以直接訪問本地文件系統而不需要任何無用的集合填充?C#.Net在遍歷大量文件時凍結

這裏是我的代碼:

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。對不起,我的英語不好

問候

+3

如果你希望我們幫助你的代碼,你需要顯示你的代碼。 [編輯你的問題](http://stackoverflow.com/posts/38083668/edit),幷包含用於傳播文件的代碼。 –

+0

聽起來像代碼中的問題,如果它永遠不會到第二個元素。可能是因爲它聽起來像你可能正在修改集合 – Plutonix

+0

抱歉忘記包括我使用Directory.GetFiles() – Yogibear

回答

10

因爲你正在做的UI線程同時工作不能刷新所有的工作。您需要在後臺線程上完成工作,然後以線程安全的方式更新UI。也切換到Directory.EnumerateFiles將使讀取第一個文件的速度更快,因此它不需要將所有記錄存儲到數組中。最後,我將ex.Message更改爲ex.ToString(),它將以這種方式顯示更多有用的信息。

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; 
     } 
    } 
} 

(代碼寫在網頁瀏覽器從內存中,因此有可能是錯誤的)

+0

對此有所反應,但我不認爲這會是問題,我會檢查這一點 – Yogibear

+2

它看起來不起作用的原因是因爲你阻止了UI,它正在工作,但它可以'告訴你它正在工作 –

+0

好吧,複製到項目中,唯一的問題是,我應該包含哪些額外的參考? – Yogibear

-1

好像你正在使用可能非常耗時的循環而沒有處理Windows的消息隊列,因此您的應用程序可能會被凍結,而它可能只是忙着做你指示它在循環中做的事情。試試這個:

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();'是非常危險的事情,你可以搞砸了如果你不小心,你的程序的內部狀態。你不應該把它當作你的第一選擇。 –

+0

這是一個快速和骯髒的修復而不改變他的原代碼。當然你的代碼更好(投票答案),但它是一個完整的重寫,而不是修復。 ;) – FjodrSo