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ようになります。

ListBoxResult

ブレークポイントを使用してコードをステップ実行すると、検索メソッドからステップアウトした直後に、BeginInvoke宣言に「ジャンプ」して戻ることがわかります。
お知らせ下さい。
ありがとう

4

1 に答える 1

1

問題は、変数を閉じていることですlineNumberBeginInvoke非同期であり、デリゲートが UI スレッドで呼び出されるのを待ちません。なんとか呼び出されるまでにlineNumber、数回インクリメントされました。

解決策は 2 つあります。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の代わりに使用して、インクリメントされる前から読み取られるようにしますBeginInvokelineNumber

于 2013-03-14T14:04:34.397 に答える