更新
如果您使用的是 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"));
}));
如果您在代码隐藏中。否则,您可以使用以下命令访问 Dispatcher(在每个 UIElement 上):
Application.Current.MainWindow.Dispatcher.BeginInvoke(...
好吧,一行就这么多,让我来复习一下:
当您想要更新 UI 控件时,正如消息中所说,您必须从 UI 线程中进行操作。有一种内置方法可以将委托(一种方法)传递给 UI 线程:Dispatcher。一旦你有了Dispatcher,你就可以通过Invoke() 或BeginInvoke() 传递一个要在UI 线程上运行的委托。唯一的区别是Invoke() 只会在委托运行后返回(即在您的情况下,ListBox 的新项目已添加)而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 上阅读有关委托的更多信息,因为这有点离题..