c# - WPF C# - 从另一个线程编辑列表框

标签 c# wpf multithreading

我意识到我正在做的事情可能很愚蠢,但我正在学习 WPF 并且想知道如何做到这一点。

我有一个带有列表框的窗口。列表框用于在程序运行时传递有关程序的状态消息。例如“服务器已启动”“IP # 的新连接”等。我希望它在后台不断更新,所以我生成了一个新线程来处理更新它,但是当我调用添加项目时,我得到了错误消息“调用线程无法访问此对象,因为另一个线程拥有它。”

知道如何从另一个线程更新列表框吗?或者在后台等。

最佳答案


更新

如果您使用的是 C# 5 和 .NET 4.5 或更高版本,您可以首先使用 asyncawait 避免进入另一个线程,例如:

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 线程执行此操作。有一种内置方式可以将委托(delegate)(一种方法)传递给 UI 线程:Dispatcher。拥有 Dispatcher 后,您可以通过 Invoke()BeginInvoke() 传递要在 UI 线程上运行的委托(delegate)。唯一的区别是 Invoke() 只会在委托(delegate)运行后返回(即在您的情况下,已添加 ListBox 的新项目),而 BeginInvoke() 将立即返回因此您调用的其他线程可以继续(Dispatcher 将尽快运行您的委托(delegate),无论如何可能会立即运行)。

我在上面传递了一个匿名委托(delegate):

delegate() {myListBox.Items.Add("new item");}

{} 之间的位是方法 block 。这称为匿名,因为只创建了一个并且没有名称(通常您可以使用 lambda 表达式执行此操作,但在这种情况下 C# 无法解析要调用的 BeginInvoke() 方法)。或者我可以实例化一个委托(delegate):

Action myDelegate = new Action(UpdateListMethod);

void UpdateListMethod() 
{
  myListBox.Items.Add("new item");
}

然后通过那个:

Dispatcher.Invoke(myDelegate);

我还使用了 Action 类,它是一个内置的委托(delegate),但您可以创建自己的 - 您可以在 MSDN 上阅读更多关于委托(delegate)的信息,因为这有点偏离主题..

关于c# - WPF C# - 从另一个线程编辑列表框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4191325/

相关文章:

c# - 获取 ListViewItem 子项

wpf - 为什么 WPF 应用程序在 Windows 7 和 Windows 8 之间看起来不同,这个问题可以修复吗?

multithreading - 控制TThread的执行流程

具有多线程的 Java Servlet

c# - Linq 的性能包含

C#:将一个文本文件的*内容*附加到另一个文本文件

c# - 使用 NPOI 编辑和保存 xlsx 会导致文件损坏

wpf - 我可以在 VS2008 中开发也可以在 Mac 上运行的桌面应用程序吗?什么方法?

java - 为什么在线程锁定 (Java/C++) 上使用比较和交换,这是由一定的争用频率决定的吗?

c# - 基于使用 NamedNetPipes 绑定(bind)解析端点地址动态创建 WCF ServiceHost