WPF C# - 从另一个线程编辑列表框 [英] WPF C# - Editing a listbox from another thread

查看:169
本文介绍了WPF C# - 从另一个线程编辑列表框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道我在做什么可能是非常愚蠢的,但我在学习WPF的中间,想知道如何做到这一点。

I realize what I'm doing is probably pretty silly, but I'm in the middle of learning WPF and would like to know how to do this.

我上有一个列表框的窗口。列表框被用来提供有关程序的状态信息,而它的运行。例如,服务器已启动,在IP#等新的方面,我想这是不断在后台更新,让我产生了一个新的线程来处理此更新,但是当我提出的要求增加一个项目,我得到的错误消息,因为不同的线程拥有它调用线程不能访问该对象。

I have a window with a listbox on it. The listbox is being used to deliver status messages about the program while it's running. For example "Server started" "New connection at IP #" etc. I wanted this to be constantly updating in the background, so I spawned a new thread for handling updating this, but when I made the call to add an item I get the error message "The calling thread cannot access this object because a different thread owns it."

任何想法,我怎么可以更新从另一个线程的列表框?或者在后台等。

Any idea how I can update the listbox from another thread? Or in the background, etc.

推荐答案



更新

如果您使用的是C#5和.NET 4.5或以上,你能避免使用混得摆在首位另一个线程异步等待,例如:

If you are using C# 5 and .NET 4.5 or above you can avoid getting on another thread in the first place using async and await, e.g.:

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;
}






简单:


Easy:

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

如果您是在代码隐藏。否则,你可以访问调度程序(这是在每个的UIElement )使用:

If you are in code-behind. Otherwise you can access the Dispatcher (which is on every UIElement) using:

Application.Current.MainWindow.Dispatcher.BeginInvoke(...

好吧那很多在一行让我过目一下:

Ok thats a lot in one line let me go over it:

当你想更新你的用户界面控制,有消息称,必须从UI线程做有内置的的方式来传递一个委托(方法)到UI线程:在调度一旦你的调度即可无论是的invoke() 中的BeginInvoke()传递一个委托要在UI线程上运行。唯一的区别是的invoke()将只返回一次委托已运行(即你的情况ListBox的新项目已添加),而的BeginInvoke()将(很快,因为它可以大概会马上反正调度运行您的代表)立即返回,以便您的您拨打电话可以继续其他线程。

When you want to update a UI control you, as the message says, have to do it from the UI thread. There is built in way to pass a delegate (a method) to the UI thread: the Dispatcher. Once you have the Dispatcher you can either Invoke() of BeginInvoke() passing a delegate to be run on the UI thread. The only difference is Invoke() will only return once the delegate has been run (i.e. in your case the ListBox's new item has been added) whereas BeginInvoke() will return immediately so your other thread you are calling from can continue (the Dispatcher will run your delegate soon as it can which will probably be straight away anyway).

我通过上面的匿名委托:

I passed an anonymous delegate above:

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

之间的{}是方法块位。因为只有一个创建这就是所谓的匿名的,并且它没有一个名字(通常是您使用的lambda表达式,但在这种情况下,C#无法解决的BeginInvoke()方法调用可以做到这一点)。或者,我可以实例化一个委托:

The bit between the {} is the method block. This is called anonymous because only one is created and it doesnt have a name (usually you can do this using a lambda expression but in this case C# cannot resolve the BeginInvoke() method to call). Or I could have instantiated a delegate:

Action myDelegate = new Action(UpdateListMethod);

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



然后通过了:

Then passed that:

Dispatcher.Invoke(myDelegate);



我还使用了动作类,这是一个内置的委托,但你可以创建你自己 - 你因为这会有点题外话..

I also used the Action class which is a built in delegate but you could have created your own - you can read up more about delegates on MSDN as this is going a bit off topic..

这篇关于WPF C# - 从另一个线程编辑列表框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆