2013-03-14 45 views
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
网址
hijk123
网址

listbox看起来就像这样:

ListBoxResult

当用断点逐句通过代码时,我可以看到,在退出搜索方法之后,它立即“跳回”BeginInvoke声明。
请指教。
谢谢

+1

这是打算的行为! 'BeginInvoke'创建一个异步操作并立即返回。 – 2013-03-14 13:59:19

回答

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从它必须增加一个机会,前阅读。

+0

'.Invoke()'很棒!将在3分钟内标记为答案:) – Yoav 2013-03-14 14:08:55