开发者

C#: Listbox CrossThreading Issues

I am trying to ac开发者_C百科cess 3 listbox elements in my program from a different thread and keep getting the cross thread exceptions. I need a way to access my listboxes from another thread and have that code in a separate class called threadUtilities.cs. This way, all my thread access related code will be in a seperate class. Can anyone please provide generic code to access any listbox from another thread?


You want to get the SynchronizationContext from the UI thread and then make it available to the background threads.

Depending on what technology you are using, a derived SynchronizationContext will be made available, but that's not of concern really; the Current property will return the one that is currently installed and both Windows Forms and WPF will install the proper one for you.

With the SynchronizationContext passed to the thread you want to make calls from, you can then call the Send method (analogous to the Invoke method) or the Post method (analogous to the BeginInvoke method) depending on your needs.

Here's an example:

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

Also, it should be mentioned that the BackgroundWorker class does all of this for you behind the scenes; if this model works for you over using the SynchronizationContext directly, then by all means, use that (the BackgroundWorker class uses SynchronizationContext internally).


Depends on whether it's WinForms or WPF. If WinForms, use the Control.Invoke method. If WPF, use the Dispatcher.

Simple WinForms sample:

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

You could make a generic function for UI access like so:

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

Use like this:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜