我意識到我在做什麼可能很愚蠢,但我正在學習WPF,並想知道如何做到這一點。WPF C# - 編輯另一個線程的列表框
我有一個窗口,上面有一個列表框。列表框正在用於在程序運行時傳遞有關程序的狀態消息。例如「服務器啓動」「在IP#的新連接」等我希望這是不斷更新在後臺,所以我產生了一個新的線程處理更新這個,但是當我打電話來添加一個項目,我得到錯誤消息「調用線程不能訪問此對象,因爲不同的線程擁有它。」
任何想法如何我可以從另一個線程更新列表框?或在後臺等。
我意識到我在做什麼可能很愚蠢,但我正在學習WPF,並想知道如何做到這一點。WPF C# - 編輯另一個線程的列表框
我有一個窗口,上面有一個列表框。列表框正在用於在程序運行時傳遞有關程序的狀態消息。例如「服務器啓動」「在IP#的新連接」等我希望這是不斷更新在後臺,所以我產生了一個新的線程處理更新這個,但是當我打電話來添加一個項目,我得到錯誤消息「調用線程不能訪問此對象,因爲不同的線程擁有它。」
任何想法如何我可以從另一個線程更新列表框?或在後臺等。
如果您正在使用C#5和.NET 4.5或以上,你能避免使用async
和await
,獲得在首位另一個線程如:
private async Task<string> SimLongRunningProcessAsync()
{
await Task.Delay(2000);
return "Success";
}
private void Button_Click(object sender, RoutedEventArgs e)
{
button.Content = "Running...";
var result = await SimLongRunningProcessAsync();
button.Content = result;
}
簡單:
Dispatcher.BeginInvoke(new Action(delegate()
{
myListBox.Items.Add("new item"));
}));
如果您處於代碼隱藏狀態。否則,你可以使用訪問調度程序(這是對每一個UIElement
):
Application.Current.MainWindow.Dispatcher.BeginInvoke(...
好的那很多一行讓我過目一下:
當你想更新UI控件你作爲消息說,必須從UI線程中完成。內置的方式可以將委託(方法)傳遞給UI線程:Dispatcher
。一旦你有了Dispatcher
,你可以通過Invoke()
的BeginInvoke()
傳遞一個委託在UI線程上運行。唯一的區別是Invoke()
只會在代理運行後纔會返回(即在你的情況下,列表框的新項目已被添加),而BeginInvoke()
將立即返回,以便您的其他線程可以繼續(調度程序將盡快運行您的委託,無論如何它可能會立即運行)。
我通過上述匿名委託:
delegate() {myListBox.Items.Add("new item");}
之間的{}是該方法塊中的比特。這稱爲匿名,因爲只有一個被創建並且沒有名稱(通常您可以使用lambda表達式執行此操作,但在這種情況下,C#無法解析調用的BeginInvoke()方法)。或者,我可以實例化一個委託:
Action myDelegate = new Action(UpdateListMethod);
void UpdateListMethod()
{
myListBox.Items.Add("new item");
}
然後通過了:
Dispatcher.Invoke(myDelegate);
我還用它內置的委託Action類,但你可以創建你自己 - 你可以讀到更多關於MSDN上的代表,因爲這是一個有點脫離主題..
你會想要使用Dispatcher.BeginInvoke。例如,如果列表框被命名爲listbox
// On worker thread
listbox.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(delegate() { listbox.Items.Add("Server started") });
這將排隊委託要在UI線程listbox
屬於執行。
嘿謝謝,你指出了正確的方向,但編者不喜歡你在這裏給了什麼。給出了關於它如何不能將lamba微積分轉換爲委託的錯誤。我能夠改變它,所以它的工作原理,任何想法是關於你的,或者你只是使用符號我不明白 – cost 2010-11-16 05:28:50
不,我只是懶得檢查自己與一個實際的程序。 – 2010-11-16 12:53:46
您還可以使用帶有匿名方法的Action委託從工作線程更新主線程。有關Action類的更多信息,你可以看看這裏:
http://msdn.microsoft.com/en-us/library/018hxwa8.aspx
如果您想更新從多個點,我建議explicitally設置委託列表框,但是如果你只是想在一個更新線程與單一的方法單點調用它可以如下進行:
listbox.Dispatcher.BeginInvoke(new Action(delegate()
{
listbox.Items.Add(item); //where item is the item to be added and listbox is the control being updated.
}));
請注意,我用的是Action類,因爲它需要封裝,有一個單獨的參數(在這種情況下,一個ListItem)的方法。
我認爲這樣做。給出的另一個答案給了我一個關於它如何不能將lamba演算轉換爲委託的編譯器錯誤。我在msdn網站上閱讀了一些內容,並搜索瞭如何使用調度程序;我修改了他給我的代碼,結果看起來完全像你在那裏得到的。回答13分鐘前,我應該剛剛刷新,哈哈。 – cost 2010-11-16 05:26:29
我太困了,寫一個完整的答案,但這裏有一個提示:環顧四周(Google,SO或MSDN)分派器。現在,我要睡覺了。 – 2010-11-16 04:56:53