If you are working on a Windows Forms project and you are using threads in some way, by accessing the controls from a thread other than the main one, you may have received this error message:
System.InvalidOperationException: ‘Cross-thread operation not valid: Control ‘TxtCounter1′ accessed from a thread other than the thread it was created on.’
You can reproduce this error in an easy way: just create a Visual Studio project of type Windows Forms, put a textbox and a button, and attach the following click event handler to the button (import the necessary namespace to use the thread object):
private void BtnStartWork1_Click(object sender, EventArgs e) { new Thread(() => { for (int i = 0; i < 10000000; i++) { TxtCounter1.Text = i.ToString(); } }).Start(); }
In this context, when you try to assign a value to TxtCounter1.Text, you will get the error above. To overcome the problem, just use the following function:
private void MakeUISafeCall(Form form, Action act) { if (form.InvokeRequired) { form.Invoke(act); } else { act.Invoke(); } }
And modify the click handler to use it:
private void BtnStartWork1_Click(object sender, EventArgs e) { new Thread(() => { for (int i = 0; i < 10000000; i++) { MakeUISafeCall(this, () => { TxtCounter1.Text = i.ToString(); }); } }).Start(); }
Let me spend some word on the MakeUISafeCall function…
The function accepts two parameters:
- form (of type Form): is the form which is the target of the operation
- act (of type Action): is the code to execute, you can pass it a lambda function
The function checks the value of the property InvokeRequired of the form. If the property returns true, then the action is executed using form.Invoke which manipulates the controls of the form in a thread safe way. Otherwise, the lambda function is executed by calling the Invoke method of the action.
That’s it…