2015-04-20 117 views
0

我們已經使用稱爲MV的MainWindow製作了一個應用程序。ListView不會更新

當main啓動時,它啓動我們的StartProgram方法作爲BackgroundWorker和Application.Run(MW);

MainWindow MW = new MainWindow(); 
BackgroundWorker.DoWork += (obj, e) => StartProgram(MW); 
BackgroundWorker.RunWorkerAsync(); 
Application.Run(MW); 

在StartProgram中,我們創建了Patient的實例,我們想要在我們的listView1中顯示。 我們通過調用這個方法,這是在MW:

public void SetListSource(Patient p) 
{ 
    ListViewItem item = new ListViewItem("woohoo"); 
    item.SubItems.Add("a"); 
    listView1.Items.Add(item); 
} 

StartProgram中的攤位,當它到達listView1.Items.Add(項目);

我們的猜測是,它等待兆瓦(MainWindow),但我們不知道如何解決它。 我們在MW中有一個按鈕,除了只向listView1發送「1」和「a」以外,其它一些相似。

private void Sort_Button_Click(object sender, EventArgs e) 
{ 
    ListViewItem item = new ListViewItem("1"); 
    item.SubItems.Add("a"); 
    listView1.Items.Add(item); 
} 

有沒有人知道如何使SetListSource(...)像Sort_Button_Click(...)一樣工作?

編輯 與調用

+1

您正在將線程從後臺線程傳入UI線程。你可能會想要「調用」。 – Lloyd

+0

非常感謝Lloyd! :d – user3265569

回答

1

解決不能從另一個線程直接修改您的GUI。您需要使用委託並調用您的控件。在你的線程,你必須做的:

CONTROL.Invoke(new Action(() => 
{ 
    CONTROL.Items.Add(item); 
} 
)); 

來源:

BackgroundWorker multithread access to form

0

可以使用Invoke,但是這可能是不必要的。您可以使用BackgroundWorker.RunWorkerCompleted事件,而不是:

BackgroundWorker.DoWork += 
    (s, e) => 
    { 
    e.Result = DoAllTheComplicatedWork(); 
    } 
BackgroundWorker.RunWorkerCompleted += 
    (s, e) => 
    { 
    // Back on the UI thread, we can do whatever we want 
    listView1.Items.Add(((SomeDTO)e.Result).Patient); 
    } 
BackgroundWorker.RunWorkerAsync(); 

或者,你可以使用await做這件事:

MW.Load += async (s, e) 
    { 
    var result = await Task.Run(() => SomeCPUWork()); 
    listView1.Items.Add(((SomeDTO)e.Result).Patient); 
    } 

關鍵的一點是,你真正想要的UI和任何你需要之間的分離在後臺做。我絕對不會將表單(或任何其他控件)傳遞給應該在不同線程上執行的任何方法。