0

我有一个小WPF应用程序需要枚举指定目录中的所有文件并检查其中是否存在某个字符串。这是搜索方法:

private void btnSearch_Click_1(object sender, RoutedEventArgs e)
{
  Thread t = new Thread(()=>search(@"c:\t", "url", true));
  t.Start();
}

private void search(string path, string textToSearch, bool ignoreCase)
{
  foreach (string currentFile in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories))
  {
    int lineNumber = 0;
    foreach (string line in File.ReadLines(currentFile))
    {
      lineNumber++;
      if (line.Contains(textToSearch))
      {
        lbFiles.Dispatcher.BeginInvoke((Action)(() =>
        {
          //add the file name and the line number to a ListBox
          lbFiles.Items.Add(currentFile + "     " + lineNumber);
        }));
      }
    }
  }
}

我的问题是,如果在文件中多次找到指定的字符串,则所有出现的行号都是后者。对于具有以下行的文本文件:

abcd
EFG
url
hijk123
url

listbox如下所示:

列表框结果

当使用断点单步执行代码时,我可以看到在退出搜索方法后立即“跳”回BeginInvoke声明。
请指教。
谢谢

4

1 回答 1

1

问题是您正在关闭变量lineNumberBeginInvoke是异步的,它不会等待在 UI 线程上调用委托。到它设法被调用时,它lineNumber已经增加了很多次。

有两种解决方案。创建一个更本地化的副本lineNumber以关闭,以便以后看不到更改:

foreach (string line in File.ReadLines(currentFile))
{
  lineNumber++;
  if (line.Contains(textToSearch))
  {
    var lineNumberCopy = lineNumber;
    lbFiles.Dispatcher.BeginInvoke((Action)(() =>
    {
      //add the file name and the line number to a ListBox
      lbFiles.Items.Add(currentFile + "     " + lineNumberCopy );
    }));
  }
}

或使用Invoke代替BeginInvoke, 以便lineNumber在它有机会增加之前读取它。

于 2013-03-14T14:04:34.397 回答