An STA, a single-threaded apartment, was created in the user interface thread of your program, thanks to the [STAThread] attribute on the main entry point Main (). Also view Thread.SetApartmentState (). STA is very code-friendly, which is not thread safe, often code that you do not see, because it is part of another program.
Like code that is involved in placing data on the clipboard, supply data in Drag + Drop operations, shell extensions that are activated when the OpenFiledialog is displayed control such as WebBrowser, which needs client code for the dispatcher so that it can raise the DocumentCompleted event. intercept windows that listen to notifications, code that relies on the availability of api to implement automation of the user interface or screen reader. Etcetera.
None of these codes should be thread safe, even if multiple threads are involved in different processes. Writing thread-safe code is generally difficult; it becomes overly difficult because the author cannot verify it. He cannot check it for all possible programs that can activate his code. Apartments were invented to solve this problem, eliminating the need to write thread-safe code.
STA is the promise you make. You swear, cross your heart - hope that you die in style, that your user interface flow behaves well, it should have a dispatcher (it's a pump, a message loop) and should never be blocked. A dispatcher is required to run the code in a thread-safe manner; this is a universal solution to the problem of the producer-consumer . And you should never be blocked, because this is likely to lead to a deadlock in the code of another programmer. What a dead end you can never debug, because you do not have the source code for this code. A Winforms, WPF, or Modern UI user interface thread always fulfills this promise, the main reason that the user interface thread is different from any other thread that you can use.
A sufficient introduction, calling Thread.Join () blocks and thereby violates the STA contract. This is very bad, so the CLR designers did something about it . They implemented Join () without blocking if it is called in the STA stream, as you know.
They did this by implementing the flavor of Application.DoEvents () . This is a very infamous way to prevent the user interface thread from hanging. This can cause a very difficult diagnosis of re-entry errors. Their version is not as bad as DoEvents (), it is very selective about what messages it allows to send in order to minimize the risk.
This is usually normal, but that does not mean that you are intentionally testing yourself. Re-login errors are very dubious errors, about as unsuccessful as streaming errors. Therefore, you should never use Thread.Join () in the user interface thread .. The .NET Framework provides excellent alternatives to the BackgroundWorker and Task classes, they both give you very good ways to execute the code (no matter what happens after Join () is called), when the thread completes.