2012-11-12 51 views
0

我使用绑定到ObservableCollection源的DataGrid来显示两列,一个文件名和一个从分析文件中获得的数字。从后台线程刷新C#DataGrid

ObservableCollection<SearchFile> fileso; 

    //... 

    private void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     /* Get all the files to check. */ 
     int dirCount = searchFoldersListView.Items.Count; 
     List<string> allFiles = new List<string>(); 
     for(int i = 0; i < dirCount; i++) 
     { 
      try 
      { 
       allFiles.AddRange(Directory.GetFiles(searchFoldersListView.Items[i].ToString(), "*.txt").ToList()); 
       allFiles.AddRange(Directory.GetFiles(searchFoldersListView.Items[i].ToString(), "*.pdf").ToList()); 
      } 
      catch 
      { /* stuff */ } 
     } 

     /* Clear the collection and populate it with unchecked files again, refreshing the grid. */ 
     this.Dispatcher.Invoke(new Action(delegate 
     { 
      fileso.Clear(); 
      foreach(var file in allFiles) 
      { 
       SearchFile sf = new SearchFile() { path=file, occurrences=0 }; 
       fileso.Add(sf); 
      } 
     })); 

     /* Check the files. */ 
     foreach(var file in allFiles) 
     { 
      this.Dispatcher.Invoke(new Action(delegate 
      { 
       int occurences; 
       bool result = FileSearcher.searchFile(file, searchTermTextBox.Text, out occurences); 

       fileso.AddOccurrences(file, occurences); // This is an extension method that alters the collection by finding the relevant item and changing it. 
      })); 
     } 
    } 

    //... 

    public static void AddOccurrences(this ObservableCollection<SearchFile> collection, string path, int occurrences) 
    { 
     for(int i = 0; i < collection.Count; i++) 
     { 
      if(collection[i].path == path) 
      { 
       collection[i].occurrences = occurrences; 
       break; 
      } 
     } 
    } 

    //... 

    public static bool searchTxtFile(string path, string term, out int occurences) 
    { 
     string contents = File.ReadAllText(path); 
     occurences = Regex.Matches(contents, term, RegexOptions.IgnoreCase).Count; 
     if(occurences>0) 
      return true; 
     return false; 
    } 

    public static bool searchDocxFile(string path, string term, out int occurences) 
    { 
     occurences = 0; 

     string tempPath = Path.GetTempPath(); 
     string rawName = Path.GetFileNameWithoutExtension(path); 
     string destFile = System.IO.Path.Combine(tempPath, rawName + ".zip"); 
     System.IO.File.Copy(path, destFile, true); 

     using(ZipFile zf = new ZipFile(destFile)) 
     { 
      ZipEntry ze = zf.GetEntry("word/document.xml"); 
      if(ze != null) 
      { 
       using(Stream zipstream = zf.GetInputStream(ze)) 
       { 
        using(StreamReader sr = new StreamReader(zipstream)) 
        { 
         string docContents = sr.ReadToEnd(); 
         string rawText = Extensions.StripTagsRegexCompiled(docContents); 
         occurences = Regex.Matches(rawText, term, RegexOptions.IgnoreCase).Count; 
         if(occurences>0) 
          return true; 
         return false; 
        } 
       } 
      } 
     } 
     return false; 
    } 

    public static bool searchFile(string path, string term, out int occurences) 
    { 
     occurences = 0; 
     string ext = System.IO.Path.GetExtension(path); 

     switch(ext) 
     { 
      case ".txt": 
       return searchTxtFile(path, term, out occurences); 
      //case ".doc": 
      // return searchDocFile(path, term, out occurences); 
      case ".docx": 
       return searchDocxFile(path, term, out occurences); 
     } 
     return false; 
    } 

但问题是,有时,当我打的更新按钮(这与上述的do_work方法启动工人),在某些时候,我得到随机零的数列,而不是正确的号码。这是为什么?我假设这是因为在更新数字列两次时会出现问题,有时在实际更新后第一次调零会得到应用,但我不确定细节。

+0

如果您的目标是.Net> 2.0,那么您想要更改为lambda语法(=>)。其次,你不应该为每个文件创建一个动作。而是有一个整体收集的方法。 Aslo,什么是fileso? –

+0

从您提供的示例中很难看出,但我不怀疑该列正在更新两次,因为您正在使用Disptacher.Invoke,它是同步的。如果您发布了AddOccurrences扩展方法和SearchFile实现,这会有所帮助。 – bryanbcook

+0

好的,我添加了方法的代码 –

回答

1

我觉得这是一个access to a modified closure

 /* Check the files. */ 
     foreach(var file in allFiles) 
     { 
      var fileTmp = file; // avoid access to modified closure 
      this.Dispatcher.Invoke(new Action(delegate 
      { 
       int occurences; 
       bool result = FileSearcher.searchFile(fileTmp, searchTermTextBox.Text, out occurences); 

       fileso.AddOccurrences(fileTmp, occurences); // This is an extension method that alters the collection by finding the relevant item and changing it. 
      })); 
     } 

的情况下,基本上发生的事情是,你传递文件变量lambda表达式,但文件将被foreach循环之前的动作实际上是被修改调用,使用临时变量来保存文件应该解决这个问题。