If you have one thread that tries to manipulate an object owned by another thread you are involved in cross threading. This can easily make your program go unstable. There is a common way this can creep into a program. If you have some task that takes a while to complete and you don't want your UI to become blocked, you naturally spin it off in a separate thread. If that task wants to display progress updates on how that task is going either with a text box or a progress bar or some other control you can get cross threading errors.
There are two ways around this. This first is pretty well documented and I'll explain it just for reference but the second approach is the one I really want to talk about. (Update: now there are three as the BackgroundWorker class can now handle a lot of this for you – also see my Cross Threading Revisited post)
Let's say you have a thread running that can detect an error and this thread raises an event so that your GUI knows about it. If your event handler in your form just goes and updates a text area you are engaging in cross threaded communication. Instead you want your event handler to call a method that checks for possible cross-threading and then use the control's Invoke method to execute the event handler in the same thread that owns the control. That looks something like this:
harder to find out about. Let me set the stage. I was programming a camera that captures images in a separate thread. This thread can kick off several events including one that tells me the image has been grabbed or that an error has occurred. I need to take that image and update and pictureBox.Image area or show the errors in a text area. Now I could use the above technique but I was actually writing a .DLL in C# for this camera to make it easier to work with. That means in my documentation I would have to explain that the images were grabbed in a separate thread and that the user of my .DLL should avoid cross threading etc. Now this is a lot to ask of a user of a .DLL and just asking for trouble. Instead I wanted the events to raise themselves in the same thread as the listener for the event. That way, the programmer using my .DLL never even needs to know the .DLL uses a separate thread. To keep things consistent here's an example of how I handled the error messages that were raised, the image processing was very similar it just had a more elaborate EventArgs class (updated the example in 2011 to use my new idiom for events and to leverage LINQ for the foreach).