2016-06-27 55 views
-1

我嘗試使用backgroundworker來實現增量搜索。在C#winform中輸入錯誤backgroundworker時發現錯誤

Winform

這樣的想法是在textbox頂部的用戶類型,併爲每個按鍵,下方的listview進行過濾,只包含包含用戶鍵入的字符的項目。

我最近了解到backgroundworker組件,因此試圖用它來過濾和更新listbox

這是textbox的事件代碼:

private void txtSearch_TextChanged(object sender, EventArgs e) 
{ 
    if (!backgroundWorker1.IsBusy) 
    { 
     backgroundWorker1.RunWorkerAsync(); 
    } 
} 

backgroundworker事件:

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
{ 
    if (txtSearch.Text != String.Empty) 
    { 
     GetTheListOfFiles(); 
     listView.Items.Clear(); << Exception occurs here ! 

     ...... //some more code to populate the listview control    
    } 
} 

問題

當我鍵入到textbox,我期待listbox立即響應我的按鍵和顯示相應地放置過濾的數據。取而代之的是約8秒鐘的停頓,然後我得到這個錯誤:

enter image description here

我相信這個問題是我已經強調了一點,但我不知道如何解決它。是否backgroundworker不能用於這個目的,或者我在執行中丟失了什麼? PS:我歡迎任何不同的方式來實現這一點。也許更有經驗的程序員有更好的解決方案嗎?

UPDATE

這裏是progresschanged事件我使用:

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e) 
{ 
    toolStripProgressBar1.Value = e.ProgressPercentage; 
    tsLabelTwo.Text = e.ProgressPercentage.ToString() + @"%"; 
} 

感謝

+0

[跨線程操作無效的可能重複:控制訪問從一個線程以外的線程創建](http://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than-the ) – MickyD

+0

BackgroundWorker的DoWork事件與您嘗試更新的UI控件位於不同的線程中。這是一個衆所周知的問題,如果您想更新控件,則需要提高在UI的同一線程中運行的ProgressChanged事件 – Steve

+0

謝謝Steve,我添加了progresschanged事件代碼。新手問題:我如何知道哪些線程可以運行?歡呼 – Nick

回答

0

如果您使用的UI線程創建一個控制,你不能訪問它認爲另一線程(例如一些後臺線程)

只需調用正在拋出交叉線程的塊

listView.BeginInvoke(new Action(() => { listView.Items.Clear(); })); 
0

如果您想更新UI,你需要調用控制:在主線程主器件接收

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e) 
    { 

     if (txtSearch.Text != String.Empty) 
     { 

      GetTheListOfFiles(); 
      listView.Dispatcher.BeginInvoke(new Action(() => listView.Items.Clear()), DispatcherPriority.Background); 
     } 
    } 
0

這是因爲你想,關於UI線程上運行從另一個控制你創建的線程,這被認爲是非法的。正確的解決方法是調用你的控件,在這種情況下是你的ListView。

listView.BeginInvoke(new Action(() => 
{ 
    listView.Items.Clear(); 
    //or perform your UI update or whatever. 
})); 

但是,如果你想成爲這樣的反叛和做違法的東西(諷刺),加上這段代碼你InitializeComponents之後();方法在窗體的構造函數中。

Control.CheckForIllegalCrossThreadCalls = false; 

但不這樣做,有一個它被稱爲「非法線程調用」原因:)

欲瞭解更多信息Control.CheckForIllegalCrossThreadCalls Property