2011-06-06 109 views
0

我想从另一个线程访问我的程序中的3个列表框元素,并不断收到交叉线程异常。我需要一种方法从另一个线程访问我的列表框,并将该代码放在一个名为threadUtilities.cs的单独类中。这样,我所有的线程访问相关的代码将在一个单独的类。任何人都可以提供通用代码来访问另一个线程的任何列表框?C#:Listbox CrossThreading问题

+0

wpf或winforms? – Jodrell 2011-06-06 14:20:09

回答

1

取决于它是WinForms还是WPF。如果WinForms,请使用Control.Invoke方法。如果是WPF,请使用Dispatcher。

简单的WinForms示例:

ListBox listBox = GetListBoxFromSomewhere(); 
if(listBox.InvokeRequired) 
    listBox.Invoke(() => listBox.Items.Add("Some item"); 
else 
    listBox.Items.Add("Some item"); 

你可以做的UI访问的通用功能,像这样:

void PerformUIOperation(Control c, Action action) 
{ 
    if(c.InvokeRequired) 
     c.Invoke(action); 
    else 
     action(); 
} 

使用这样的:

PerformUIOperation(listBox,() => listBox.Items.Add("Some item"); 
+0

我添加了一个例子。或者,使用BackgroundWorker创建线程,并使用ProgressChanged事件访问UI。 – Sven 2011-06-06 14:25:14

+0

是的,即时通讯使用后台工作人员,我在另一类,所以我不能直接访问列表框。我读了关于如何使用delagtes来完成这种操作的例子,但是这些例子只包含了每个委托的一个列表框,并且他们也使用了表单类中的delagate,因此有权访问列表框元素 – Paul 2011-06-06 14:25:32

+0

hmmm让我试试 – Paul 2011-06-06 14:28:27

2

你想要得到的SynchronizationContext从UI线程,然后使其可用于后台线程。

根据您使用的是什么技术,导出SynchronizationContext将会变得可用,但那不是真正关心的问题; Current property将返回当前安装的那个,Windows窗体和WPF将为您安装适当的一个。

随着SynchronizationContext传递给你想拨打电话的,然后你可以调用Send method(类似于Invoke method)或Post method(类似于BeginInvoke method)根据您的需要线程。

下面是一个例子:

public void Button1_OnClick(sender object, EventArgs e) 
{ 
    // Get the current SynchronizationContext. 
    // NOTE: Must make the call on the UI thread, NOT 
    // the background thread to get the proper 
    // context. 
    SynchronizationContext context = SynchronizationContext.Current; 

    // Start some work on a new Task (4.0) 
    Task.Factory.StartNew(() => { 
     // Do some lengthy operation. 
     ... 

     // Notify the user. Do not need to wait. 
     context.Post(o => MessageBox.Show("Progress")); 

     // Do some more stuff. 
     ... 

     // Wait on result. 
     // Notify the user. 
     context.Send(o => MessageBox.Show("Progress, waiting on OK")); 
    }); 
} 

而且,应该提到的是,BackgroundWorker class做这一切为你在幕后;如果这种模式直接适用于SynchronizationContext,那么请使用它(BackgroundWorker类内部使用SynchronizationContext)。

+0

不知道这个+1,并且自从.Net 2.0开始 – Jodrell 2011-06-06 14:33:55

+0

你能提供一个如何做到这一点的例子吗?我在编码方面全新,这是我第一次使用背景技术。如何声明和使用SynchronizationContext。 (即通过线索你想打电话等) – Paul 2011-06-06 14:38:59

+0

@Paul:用例子更新答案。 – casperOne 2011-06-06 15:31:13