Click here to Skip to main content
Click here to Skip to main content

How to solve "Cross thread operation not valid"

By , 7 Oct 2006
 
how to access a control from another thread which didn't create this control.

I faced this issue more than 1 time, I decided to collect info about it and made some changes on the code to simplify this problem to you cause it's really annoying and confusing to work with threading stuff. Here is a small code solves this problem FOREVER and in ANY case.

Error:

Cross thread operation not valid: Control "XXXXXXXXXX" accessed from a thread other than the thread it was created.

Solution:

1- Create your thread:

 Private Strt As System.Threading.Thread   


2- Start your thread wherever you want:

  Strt = New System.Threading.Thread(AddressOf MyThread1)
  Strt.Start()


3- Add the thread sub (MyThread1) and put whatever you want and remember that the lines which access a control from this thread will be separated to into another sub (the Delegate sub)

 Sub MyThread1
       ' Working code
       ' Working code
       ' Working code
       ' Working code
       ' Working code
       ' Working code

       AccessControl()

End Sub


From the previous code you will notice 2 things:
1st: AccessControl the sub which will be delegated.
2nd: ' Working code - which doesn't need a delegate to get it work. In other mean, it doesn't show up the error message you receive.

4- and finally, add the delegated sub:

Private Sub AccessControl()
        If Me.InvokeRequired Then
            Me.Invoke(New MethodInvoker(AddressOf AccessControl)) 
        Else
    ' Code wasn't working in the threading sub
    ' Code wasn't working in the threading sub
    ' Code wasn't working in the threading sub
    ' Code wasn't working in the threading sub
    ' Code wasn't working in the threading sub
            Button2.Visible = True
            Button3.Visible = True
            Opacity = 1
            ShowInTaskbar = True
        End If
    End Sub


From the previous code you will notice that all the codes which wasn't working in the threading sub will be added after "Else" line.
examples for some codes which needs to be delegated:
(Control).Visible
Me.Opacity
Me.ShowInTaskbar

I hope i simplified it enough, and now no worry about this issue again.
Special thanks to jmcilhinney for his help. You can also find this article at this link:
http://www.bitsnips.com/forums/viewtopic.php?p=102#102
Have a nice day :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Elagizy
Software Developer (Senior) InfraDrive
Egypt Egypt
Member
Egyptian freelance programmer and the founder of InfraDrive, Inc.
 
Check:
http://www.infradrive.com
http://www.bitsnips.com

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionCross threadmembersabuni5 Jan '13 - 11:05 
Thanx guys this was vey useful to me
GeneralMy vote of 5memberDisactive16 Dec '12 - 5:52 
:-*
QuestionNice ArticlememberSatish_Tijare21 Oct '12 - 19:57 
Grate article. It solved my problem. Thank you very much
GeneralMy vote of 5 [modified]memberOsama El Shammari24 Jul '12 - 11:30 
Thank you... really simple and easy solution...
Thank you again...

modified 23 Mar '13 - 4:15.

GeneralYou Rock!memberTimmyTwins3 Jul '12 - 12:55 
How you just tell, it solved my problem! Big Grin | :-D thank u very much!
GeneralRe: You Rock!memberJoBrittain6 Jul '12 - 12:18 
I agree Big Grin | :-D
QuestionMy votememberkmf7 Dec '11 - 23:10 
Many thanks
GeneralMy vote of 5membergafoor123 Nov '11 - 19:55 
Excellent Code Snippet. It was make easy for me to Update my Controls while Timer is Running......
QuestionAlternative Methodmemberjlopez78814 Oct '11 - 8:24 
I'd like to do it a little more differently:
 

public delegate R InvokeAction<R>();
public delegate R InvokeParameterizedAction<R>(params object[] data);
 

public static void CrossThread<T>(this T t, InvokeAction action) where T : Control
        {
            if (t.InvokeRequired)
                t.Invoke(action);
            else
                action();
        }
public static R CrossThread<T, R>(this T t, InvokeParameterizedAction<R> action, params object[] data) where T : Control
        {
            if (t.InvokeRequired)
                return (R)t.Invoke(action, data);
            else
                return action(data);
        }
Then it can be accessed like so from your control:
TextBoxObject.CrossThread(()=>
{
// ... Do stuff here from another thread
});
// OR

TextBoxObject.CrossThread((textbox,newtext) =>
{
textbox.Text = newtext;
}, TextBoxObject,"Update Text");

GeneralMy vote of 5memberSunasara Imdadhusen9 Sep '11 - 3:19 
Excellent!
GeneralMy vote of 5memberNanda_MR13 Mar '11 - 23:34 
My Vote is 5
Got a global soluation. Smile | :)
GeneralI laughed a lot :)memberMember 102216226 Oct '10 - 23:17 
There are 2 problems in this "great and simple solution". First - sometimes Control.Invoke stucks, so calling thread is stuck inside the method. Some smart persons recommend to use BeginInvoke Laugh | :laugh: but it doesnt solve the problem, in some cases the "else" branch will not be called, (for example, when Message Queue is overheaded).
And the second Smile | :) )) When the control is INVISIBLE, its handle is destroyed, so InvokeRequired returns FALSE Smile | :) try to do the followin - create form, call Form.Hide() and then check what Form.InvokeRequired returns. You're gonna pleasantly surprised Smile | :) so you background thread will enter "else" branch and throws your favorite Exception.
GeneralYou missed the point.memberElagizy27 Oct '10 - 4:14 
You must be aware of when calling controls inside this method. That method will run codes without being threaded so if there is any problem in your control then that's the problem which leads to make the application hangs because the method executes codes in the main thread (application) not the thread you've created so when the control hangs, the application hangs. My solution works perfectly with any standard control.invoke or a well constructed custom control. The windows application itself is a primary thread, and when you create another thread and calling controls that are property of the windows application that leads to "Cross thread operation not valid" because there are 2 threads trying to deal with 1 control at the same time.
 
For the 2nd issue, you must not set the visibility of the control to false. Instead, set the position of the control behind another control. That will fix it Wink | ;)
Best Regards,
Ehab El-agizy

GeneralMy vote of 5memberL3CodeProject22 Oct '10 - 10:47 
Who would have thought. Thanks for publishing a resolution to thread update for a DataGrid.DataSource refresh problem.
GeneralSimply Great!!memberrahu_12221 Sep '10 - 20:37 
Thanks for writting such a nice and helpful article.
This article has reduced my lot of overhead to write delegates whenever cross-thread exception was occuring for each controls.
Thanks a lot once again. Keep up the good work!!
- Rahul Chitte Cool | :cool:
Generalthanks :) :)memberArunJoseph 471639512 Sep '10 - 5:30 
thanks a lot a loooottttt Smile | :)
GeneralThank Youmemberjb.jigar30 Jul '10 - 8:39 
Excellent Work !!
GeneralMy vote of 5memberjb.jigar30 Jul '10 - 8:11 
Excellent !!
Thanks
QuestionWhat if the method is a handler of a PropertyChanged Event from an updated class variable?memberbretddog1 Apr '10 - 0:01 
In my form class:
 Private Sub LastUpdate(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
        If Me.InvokeRequired Then
            Me.Invoke(New MethodInvoker(AddressOf LastUpdate))
        Else
            Me.textbox1.Text = e.PropertyName
....
 
My code does not accept the "AddressOf LastUpdate" part.. obviously cause I don't understand how to implement this... ?
AnswerRe: What if the method is a handler of a PropertyChanged Event from an updated class variable?memberElagizy1 Apr '10 - 7:53 
You can't set parameters for LastUpdate. Check the stated example. If you need to path some variables through the function, set this variables outside.
Best Regards,
Ehab El-agizy

GeneralIf it doesn't work for anyone try this...memberMichaelsg22 Mar '10 - 23:14 
I found after setting the control attributes they set (on the right form) but not on the right instance of the form or something like that, so they did not update the controls on the frmMain i had open, so setting the attributes did nothing.
 
Heres the line i added (i was also working on it in a module instead of a form window):
 
    Private Sub UpdateLabel()
        Dim tmpMain As frmMain = Application.OpenForms.Item("frmMain")
        If tmpMain.InvokeRequired Then
            tmpMain.Invoke(New MethodInvoker(AddressOf UpdateLabel))
        Else
            tmpMain.lblUsersCon.Text = "blah de blah blah"
        End If
    End Sub
 
Michael
GeneralRe: If it doesn't work for anyone try this...memberElagizy1 Apr '10 - 7:56 
That's because you've created the form inside the invoker itself!
Best Regards,
Ehab El-agizy

GeneralWrap 'em up :)memberDerek R. White13 Mar '10 - 15:27 
http://javaflowswithin.blogspot.com/2010/03/c-threadsafecontrol.html[^]
GeneralThat was absolutely greatmemberchowdarysway15 Oct '09 - 22:34 
Wow!, i have been searching for a similar article for a long time now on google, thank god i found it at last.
 
To the author
Keep up the good work, you are helping many people in the world
GeneralAccess the controls in ThreadmemberMuhammad Ghufran13 Aug '09 - 3:21 
Please have look to find more solutions, related to cross thread.
File Compressor and Decompressor[^]
 
In the race for excellence, there is no finish line.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 7 Oct 2006
Article Copyright 2006 by Elagizy
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid