STA definition: "single thread affinity" or "single threaded flat"; and how they relate

I am working with WPF and reading STA stuff. Two questions:

1) STA is defined as standing for both "single-threaded" and "single-threaded apartment" by different entries. It says about the former: https://msdn.microsoft.com/en-us/library/ms750441(v=vs.110).aspx It speaks about the latter: https://msdn.microsoft.com/en-us/ library / ms742522 (v = vs.110) .aspx

What is it, or can STA refer to any of these related concepts?

2) Is it correct to describe their relationship as: Single-threaded flat is a model used by various Windows components, thread affinity is a characteristic of this model?

Thank.

+3


source to share


3 answers


STA stands for "One-Thread Apartment". This is a COM concept that has nothing to do with WPF. WPF designers learned of bugs in .NET 1.x, many programmers wrote programs that violated thread safety requirements and made their programs very time-consuming. Therefore, they added more runtime checks to the .NET framework code to help them get out of trouble.

While this is a pure COM concept, the underlying principle is quite universal. By declaring an STA thread, you are promising that the code you write will behave well. You write well thought out code by running a dispatcher loop (Application.Run) and never block code that runs on a thread. Breaking this promise causes a dead end.

The vast majority of .NET classes, as well as most of the code you write yourself, are unsafe. There are two main ways to make this code thread safe. The first is the approach you take on a class like List <>, which you put blocking statements in your code to ensure that the List object can only be accessed one thread at a time.

This usually works fine, but the more complex the class becomes, the harder it is to figure out where to put the lock statements and the more likely such locks are to cause a deadlock. The only other option you need to keep your code threaded is to ever make method calls on the same thread. All WPF components are like this, you have to call Dispatcher.Begin / Invoke () from the worker thread to set their properties or call their methods. Now you can say that the object has a thread-affinity, it is only accessible from the thread that created it.



The WPF designers wanted to add these runtime checks to mislead the programmer that they are using a WPF component. The component can only work with a thread called Application.Run (), so Dispatcher.Begin / Invoke () will work. The problem is that they cannot determine if a thread will respond to Application.Run (). This often happens later. A promise is needed.

So they borrowed the COM promise, the state of the apartment in the thread is always given and gives a decent hint of how it will behave. No guarantee, just a decent hint. The main thread of a WPF application is almost always appropriate, it is STA thanks to the [STAThread] attribute on the Main () entry point, and the project template ensures that it calls Application.Run (). And the Task thread or thread-pool is in the MTA and will never call Application.Run (), so this is a very hostile place for a WPF component.

The exception they throw does not give the programmer a problem. Note how you can suppress this exception very easily. All you have to do is call Thread.SetApartmentState () to fulfill the promise. But of course you are now flying without a safety net, WPF can no longer tell you that you are doing it wrong, now you completely need to write the code correctly. You should call Application.Run () even if you usually don't want to.

+8


source


STAThreadAttribute

tells the .NET VM to set up the original COM thread of the apartment to a single threaded apartment (STA).

1) This is what STA, A means for an apartment, not for proximity.

The main problem here is dealing with external COM components, usually GUI controls such as a control WebBrowser

that instantiates an embedded IE component that must support STA.

2) Yes, STA implies thread merging, which is a requirement for Win32 windows and window messages in general.



In practice, you can either mark Main()

with [STAThread]

or create a new thread, set it flat , and then start it while you start the message loop later, for example Application.Run()

or WaitOne

on WaitHandle

, as it will use CoWaitForMultipleHandles

.

So, here are the implications of an attribute STAThread

or starting a thread configured for an STA:

  • The virtual machine will call CoInitializeEx

    withCOINIT_APARTMENTTHREADED

  • You must run a message loop to provide interconnect calls to apartment objects.

  • Even if you don't expect cross-network calls, you should still run a message loop because STA COM components may require one, usually due to the use of GUI APIs, directly or indirectly, for example. shell functions

  • WaitOne

    and WaitAny

    will use pending message forwarding, for example, CoWaitForMultipleHandles

    instead of a simple WaitForSingleObjectEx

    /WaitForMultipleObjectsEx

  • WaitAll

    not supported because the underlying API will wait on all handles and message queues, there is no passive way to wait on all handle set or message queues

+2


source


  • STA stands for "single threaded apartment" - the COM model for handling multi-threaded access to a COM object. The interconnection of threads is a consequence of this model - when one thread has entered an apartment STA, no other thread can enter that apartment. And the owner of the thread of the apartment cannot be changed.
  • It is correct to describe their relationship as: Single-threaded apartment is the model used to handle multi-threaded access to a COM object , the affinity of the thread is the implication of this model.
+2


source







All Articles