2012-10-25 45 views
0

這是mt第一次嘗試編寫一個不基於web的程序,而且我第一次用C#編寫任何東西。跨線程調用?

我需要一個監視文件夾的程序,但我無法讓它工作。 我已經使用這個帖子Using FileSystemWatcher with multiple files的例子,但正試圖使它成爲一種形式。

我目前的問題出現在ProcessQueue函數中,其中fileList顯然是在另一個線程中定義的。 每當一個文件實際上被提交到監視的文件夾我得到一個錯誤,使用fileList是一個十字線程調用

任何人都可以解釋這個錯誤,以及如何解決它?

namespace matasWatch 
{ 
    public partial class Form1 : Form 
    { 
     private int n = 1; 
     private bool isWatching = false; 
     private List<string> filePaths; 
     private System.Timers.Timer processTimer; 
     private string watchedPath; 
     private FileSystemWatcher watcher; 

     public Form1() 
     { 
      filePaths = new List<string>(); 
      watchedPath = "C:\\Users\\username\\Desktop\\test"; 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      if (!isWatching) 
      { 
       button1.Text = "Stop"; 
       isWatching = true; 
       watcher = new FileSystemWatcher(); 
       watcher.Filter = "*.*"; 
       watcher.Created += Watcher_FileCreated; 
       watcher.Error += Watcher_Error; 
       watcher.Path = watchedPath; 
       watcher.IncludeSubdirectories = true; 
       watcher.EnableRaisingEvents = true; 
      } 
      else { 
       button1.Text = "Watch"; 
       isWatching = false; 

       watcher.EnableRaisingEvents = false; 
       watcher.Dispose(); 
       watcher = null; 
      } 
     } 

     private void Watcher_Error(object sender, ErrorEventArgs e) 
     { 
      // Watcher crashed. Re-init. 
      isWatching = false; 
      button1_Click(sender, e); 
     } 

     private void Watcher_FileCreated(object sender, FileSystemEventArgs e) 
     { 
      filePaths.Add(e.FullPath); 

      if (processTimer == null) 
      { 
       // First file, start timer. 
       processTimer = new System.Timers.Timer(2000); 
       processTimer.Elapsed += ProcessQueue; 
       processTimer.Start(); 
      } 
      else{ 
       // Subsequent file, reset timer. 
       processTimer.Stop(); 
       processTimer.Start(); 
      } 
     } 

     private void ProcessQueue(object sender, ElapsedEventArgs args) 
     { 
      try 
      { 
       fileList.BeginUpdate(); 
       foreach (string filePath in filePaths) 
       { 
        fileList.Items.Add("Blaa"); 
       } 
       fileList.EndUpdate(); 
       filePaths.Clear(); 
      } 
      finally 
      { 
       if (processTimer != null) 
       { 
        processTimer.Stop(); 
        processTimer.Dispose(); 
        processTimer = null; 
       } 
      } 
     } 
    } 
} 
+0

你忘了告訴我們錯誤是什麼。您將原因診斷爲「fileList顯然是在另一個線程中定義的」,但您沒有告訴我們您嘗試診斷原因的錯誤。究竟出了什麼問題? –

+0

您可能需要使用'Form.Invoke'來操作另一個線程中的UI元素。 –

+0

看起來像你的BeginUpdate是異步的,可能是你正在嘗試從該方法更新主窗體上的內容。你不能這樣做 –

回答

1

我假設fileList是一個windows窗體控件。 ProcessQueue方法從默認爲後臺線程的計時器線程中調用。 fileList控件駐留在UI線程中。您需要使用表單的Invoke()方法將其傳遞給委託,以更新fileList控件。

Invoke(new Action(() => 
    { 
     fileList.BeginUpdate(); 
     foreach (string filePath in filePaths) 
     { 
      fileList.Items.Add("Blaa"); 
     } 
     fileList.EndUpdate(); 
     filePaths.Clear();  
    })); 
+0

工作,謝謝 – Zlug

0

嘗試使用的System.Windows.Forms.Timer代替System.Timers.Timer所以在UI線程上執行的計時器滴答事件。

查看here瞭解更多詳情。