STAThread und Multithreading

102

Aus dem MSDN-Artikel zu STAThread:

Gibt an, dass das COM-Threading-Modell für eine Anwendung Single-Threaded-Apartment (STA) ist.

(Als Referenz ist das der gesamte Artikel .)

Single-Threaded-Wohnung ... OK, das ging mir über den Kopf. Außerdem habe ich irgendwo gelesen, dass dieses Attribut, wenn Ihre Anwendung nicht COM-Interop verwendet, überhaupt nichts bewirkt. Was genau macht es und wie wirkt es sich auf Multithread-Anwendungen aus? Sollten Multithread-Anwendungen (zu denen alles gehört, was Timers verwendet, bis hin zu asynchronen Methodenaufrufen, nicht nur Threadpools und dergleichen) MTAThread verwenden, auch wenn dies nur aus Sicherheitsgründen erfolgt? Was machen STAThread und MTAThread eigentlich?

Matthew Scharley
quelle

Antworten:

60

Apartment Threading ist ein COM-Konzept; Wenn Sie COM nicht verwenden und keine der von Ihnen aufgerufenen APIs COM "under the cover" verwendet, müssen Sie sich keine Gedanken über Apartments machen.

Wenn Sie sich der Wohnungen bewusst sein müssen, können die Details etwas kompliziert werden . Eine wahrscheinlich stark vereinfachte Version ist, dass COM-Objekte, die als STA gekennzeichnet sind, auf einem STAThread ausgeführt werden müssen und COM-Objekte, die als MTA gekennzeichnet sind, auf einem MTA-Thread ausgeführt werden müssen. Mit diesen Regeln kann COM Anrufe zwischen diesen verschiedenen Objekten optimieren und das Marshalling dort vermeiden, wo es nicht erforderlich ist.

Bruce
quelle
7
Das ist zu stark vereinfacht. Multithread-Objekte können in jedem Thread ausgeführt werden. Objekte mit Wohngewinde können nur in der Wohnung ausgeführt werden, in der sie erstellt wurden.
1800 INFORMATION
28
Ein Aufruf von einem STA-Objekt in einem STA-Thread an ein MTA-Objekt wird an einen MTA-Thread weitergeleitet (es sei denn, das MTA-Objekt implementiert den Marshaller mit freiem Thread). Wie gesagt, die Details können kompliziert werden. (Ich habe einige Jahre im COM-Team gearbeitet, grinsen )
Bruce
9
Manchmal müssen Sie sich dessen bewusst sein, auch wenn Sie COM nicht direkt verwenden. Ein Thread muss das Single-Threaded Apartment-Modell verwenden, wenn grafische Fenster angezeigt werden. Aus diesem Grund wird [STAThread] in einer Windows Forms-Anwendung immer über der Hauptmethode angezeigt.
Justin Ethier
6
Könnte so etwas wie ein Schrift- oder Dateidialog COM nicht verwenden, ohne dass Sie es wissen? Ich würde davon ausgehen, dass dies intern der Fall ist. Würde dies nicht bedeuten, dass für fast jede Windows Forms-Anwendung STAThread festgelegt werden muss? Verzeihen Sie meine naive Annahme, da ich die COM-Programmierung noch nicht durchgeführt habe.
Brett Ryan
4
Eine detailliertere Antwort für diejenigen, die interessiert sind: stackoverflow.com/questions/4154429/apartmentstate-for-dummies
jgauffin
3

Damit wird sichergestellt, CoInitializedass COINIT_APARTMENTTHREADED als Parameter angegeben wird. Wenn Sie keine COM-Komponenten oder ActiveX-Steuerelemente verwenden, hat dies keinerlei Auswirkungen auf Sie. Wenn Sie dies tun, ist dies von entscheidender Bedeutung.

Steuerelemente mit Apartment-Thread sind effektiv Single-Thread-Steuerelemente. Anrufe, die an sie gesendet werden, können nur in der Wohnung verarbeitet werden, in der sie erstellt wurden.

Einige weitere Details von MSDN:

Objekte, die in einer Single-Threaded-Wohnung (STA) erstellt wurden, empfangen Methodenaufrufe nur vom Thread ihrer Wohnung, sodass Aufrufe serialisiert werden und nur an den Grenzen der Nachrichtenwarteschlange ankommen (wenn die Win32-Funktion PeekMessage oder SendMessage aufgerufen wird).

Objekte, die in einem COM-Thread in einem Multithread-Apartment (MTA) erstellt wurden, müssen jederzeit Methodenaufrufe von anderen Threads empfangen können. Normalerweise implementieren Sie eine Form der Parallelitätskontrolle im Code eines Multithread-Objekts mithilfe von Win32-Synchronisationsprimitiven wie kritischen Abschnitten, Semaphoren oder Mutexen, um die Daten des Objekts zu schützen.

Wenn ein Objekt, das für die Ausführung in der neutralen Thread-Wohnung (NTA) konfiguriert ist, von einem Thread aufgerufen wird, der sich entweder in einer STA oder in der MTA befindet, wird dieser Thread an die NTA übertragen. Wenn dieser Thread anschließend CoInitializeEx aufruft, schlägt der Aufruf fehl und gibt RPC_E_CHANGED_MODE zurück.

1800 INFORMATIONEN
quelle
Der MSDN-Artikel ist aus COM-Sicht hilfreich. Können Sie mir jedoch mitteilen, wann .NET als CoInitialize()Antwort auf das STAThreadAttribut / aufruft ApartmentState? Hinweis: Der Artikel zu MSDN finden Sie hier: CoInitializeEx-Funktion .
jrh
Hat Gewinde-> SetApartment verwenden CoInitialize()intern? Ich habe das STAThread-Attribut bis ganz nach unten verfolgt, aber der Pfad ist kalt geworden (ich kann die Quelle für nicht finden Thread::SetApartment). Ist die Thread-Klasse von thread.h (der COM-Thread.h) irgendwo dokumentiert? Ist es MFC, ATL oder etwas anderes?
jrh
@jrh Ich weiß nicht mehr Details als das sorry
1800 INFORMATION
-15

STAThread wird vor der Hauptfunktion eines C # GUI-Projekts geschrieben. Es macht nichts anderes, als dass das Programm einen einzelnen Thread erstellen kann.

Zeinth
quelle