Click to See Complete Forum and Search --> : Cross thread communication - VS08


joe1985
September 26th, 2008, 07:04 PM
Visual Studio 2008

I've got


private Image ModifyPicture(Bitmap bitmap)


I'd like to call that method on another thread and then set the Image property of a pictureBox on my form to that Image.

I've searched online and I can't really find any good examples.

Every example is a math example where they write the result to a console window.

I am editing this picture, and its causing my form to freeze during that method.

I am just doing this for fun and I'd like to know how to do it correctly. I already know I can set CheckForIllegalCrossThreading = false.

Thanks for your input.

Mutant_Fruit
September 26th, 2008, 08:36 PM
That check should be left enabled. It lets you know that you're doing something wrong. And yes, every time that fires, you *are* doing something wrong.

The best idea is to ensure that you don't do any illegal cross-thread calls (i.e. updating winforms stuff outside of the main loop). Otherwise you can easily end up with random unexplainable crashes.

darwen
September 27th, 2008, 05:44 AM
Have a look at InvokeRequired ('http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx').

The page gives details about how to make cross-thread UI calls.

Darwen.

Frankgr
August 26th, 2010, 12:40 AM
The simplest possible cross thread to GUI implementation - and this can serve about any need - can be coded like this:

public delegate void serviceGUIDelegate();
private void updateGUI()
{
this.Invoke(new serviceGUIDelegate(serviceGUI));
}

"serviceGUI()" is a GUI thread level method within the Form Control (this) that can change as many GUI control parameters as you want. Call "updateGUI()" from the non-GUI thread. Parameters can be added to pass values, or (probably faster) use class scope variables with locks on them as required (if there is any possibility of a clash between thread accesses to them that could cause instability). Use BeginInvoke instead of Invoke if the non-GUI thread is time critical, keeping in mind that calling BeginInvoke too frequently can clog the message pump.

Personally I prefer this to the Background Worker or any of the more complex techniques. It nicely demonstrates how delegates can clean up otherwise messy situations. I've had no problem updating many GUI Forms (10 in one case) at a time with one call, with separate graphs on each, operating at fairly high real-time update speeds (10 ms per full 8 data channel sample) - and still maintaining under 5% processor usage on my ancient 2003 Dell.

Shannon McCoy
May 18th, 2011, 01:00 PM
Here is an even easier way. Just put this code at the top of your main form.

public static void FormSafeInvoke< T >( this T a_Control, Action< T > a_Action )
where T : Control
{
if( a_Control.InvokeRequired )
a_Control.Invoke( new Action< T, Action< T > >( FormSafeInvoke ),
new object[] { a_Control, a_Action } );
else
a_Action( a_Control );
}


And call it like this.

myLabel.FormSafeInvoke( a_Label => a_Label.Text = "This works" );

Done.

I will work for anything derived from the Control class. If you want to use it on something derived from something else the just change the where T: Control to where T : WhateverType

Enjoy

Shannon McCoy
May 18th, 2011, 01:03 PM
Oh almost forgot. Put it in your namespace but outside your class so that your other forms and controls in your project can use it. Also the a_Label is just my notation and is an argument it could be x or c or any other name. Its not one of your objects.