2013-03-14 63 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