Calling a form control from a (worker)thread.

When using multiple threads controls on a form cannot be called directly. Doing so will throw an exception like ‘Cross-thread operation not valid: Control ‘dc’ accessed from a thread other than the thread it was created on.’

Fortunately there is a rather simple solution for this problem. Use the Invoke method to execute code in the GUI thread.

The invokemethod has the following prototype

public void Invoke(System.Delegate delegate);

For example: from a worker thread a button on a form (Form1)  must be pressed. From inside the thread use the following construct to perform it thread safe.

Invoke((MethodInvoker)delegate
{
   Button1.Click();
});

Invoke is a member of the Control class. To make it work use a control created in the same thread.  In the example above you can use Form1.Invoke() or Button1.Invoke() since they both are created in the same thread.

MethodInvoker is a default delegate definition. Its definition is  delegate void MethodInvoker;

External delegates:

Of course the delegate can be external as well, sometimes this is favorable to get cleaner code or if the delegate is frequently used.

delegate void ClickTheButton();
void clickTheButton()
{
   ...
}

Inside the method

ClickTheButton clickTheButtonDelegate = clickTheButton;
Invoke(clickTheButtonDelegate);

 

Delegates with parameters

Delegates can also be called with parameters . This uses the second form of Invoke()

public void Invoke(System.Delegate delegate, object [] args);

void clickTheButton(int value)
{
   ...
}

delegate void ClickTheButton(int);

Inside the method

 ClickTheButton clickTheButtonDelegate = clickTheButton;
 Invoke(clickTheButtonDelegate, new object[] {1});
Lastest update in October 2011, inital post in October 2011

Write a comment

I appreciate comments, suggestions, compliments etc. Unfortunately I have no time to reply to them. Useful input will be used for sure!