2011-06-06 35 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