2008-10-03 4 views
97

Aus dem MSDN-Artikel auf STAThread:STAThread und Multithreading

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

(Als Referenz ist das the entire article.)

Singlethread-Apartment ... OK, das über den Kopf ging. Außerdem habe ich irgendwo gelesen, dass, wenn Ihre Anwendung COM-Interop verwendet, dieses Attribut überhaupt nichts tut. Was genau tut es und wie wirkt es sich auf Multithread-Anwendungen aus? Sollten Multithread-Anwendungen (die von irgend jemandem mit Timer bis hin zu asynchronen Methodenaufrufen und nicht nur Threadpools und Ähnlichem reichen) MTAThread verwenden, selbst wenn es "nur um sicher zu gehen" ist? Was machen STAThread und MTAThread eigentlich?

Antwort

58

Apartment-Threading ist ein COM-Konzept; Wenn Sie COM nicht verwenden und keine der APIs, die Sie aufrufen, COM unter dem Deckblatt verwenden, müssen Sie sich keine Sorgen um die Apartments machen.

Wenn Sie auf Wohnungen achten müssen, dann können die Details erhalten a little complicated; Eine wahrscheinlich zu stark vereinfachte Version besteht darin, dass COM-Objekte, die als STA gekennzeichnet sind, auf einem STAThread ausgeführt werden müssen und COM-Objekte, die als MTA markiert sind, in einem MTA-Thread ausgeführt werden müssen. Mit diesen Regeln kann COM Aufrufe zwischen diesen verschiedenen Objekten optimieren und Marshallen dort vermeiden, wo es nicht erforderlich ist.

+7

Das ist zu stark vereinfacht. Multithread-Objekte können in jedem Thread ausgeführt werden. Apartment-Threading-Objekte können nur in der Wohnung ausgeführt werden, in der sie erstellt wurden. –

+27

Ein Aufruf von einem STA-Objekt in einem STA-Thread an ein MTA-Objekt wird zu einem MTA-Thread marshallen (außer das MTA-Objekt implementiert den Freethread-Marshaller) . Wie ich schon sagte, die Details können kompliziert werden. (Ich habe einige Jahre am COM-Team gearbeitet * grins *) – 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 es grafische Fenster anzeigt. Aus diesem Grund wird [STAThread] immer über der Hauptmethode in einer Windows Forms-Anwendung angezeigt. –

3

Was dies bewirkt, stellt sicher, dass CoInitialize COINIT_APARTMENTTHREADED als Parameter genannt wird. Wenn Sie keine COM-Komponenten oder ActiveX-Steuerelemente verwenden, hat dies keinerlei Auswirkungen auf Sie. Wenn Sie das tun, dann ist es irgendwie entscheidend.

Steuerelemente, die Wohnung Gewinde sind Gewinde effektiv Single sind, um sie Anrufe können nur in der Wohnung verarbeitet werden, dass sie erstellt wurden

mehr im Detail von MSDN.

Objekte erstellt in eine Single-threaded- Apartment (STA) erhält Methode aufruft nur von ihrer Wohnung des Threads, sind so Anrufe serialisiert und nur bei Nachricht-queue Grenzen (wenn die Win32-Funktion PeekMessage oderankommenSendMessage wird aufgerufen).

auf einem COM Faden erzeugten Objekte in einer Multi-Thread- Wohnung (MTA) muss Lage seiner Methode erhalten von anderen Threads zu jeder Zeit aufruft. Sie würden typischerweise eine Form von Nebenläufigkeitssteuerung in einem multithreaded Code des Objekts implementieren mit Win32 Synchronisations Primitiven wie kritischen Abschnitten, Semaphore oder mutexes des Daten für das Objekt zu schützen.

Wenn ein Objekt, das durch ein Gewinde so konfiguriert ist, dass in entweder einer STA ist aufgerufen Lauf in der neutralen Gewinde Wohnung (NTA) oder den MTA, die Gewinde Transfers zum NTA. Wenn dieser Thread anschließend CoInitializeEx aufruft, schlägt der Aufruf fehl und gibt RPC_E_CHANGED_MODE zurück.

+0

Der MSDN-Artikel ist aus einer COM-Perspektive hilfreich, aber können Sie mir sagen, wenn .NET "CoInitialize()" als Reaktion auf das Attribut "STAThread"/"ApartmentState" aufruft? Hinweis: Der Artikel zu MSDN befindet sich hier: [CoInitializeEx-Funktion] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms695279%28v=vs.85%29.aspx). – jrh

+0

@jrh ruft es auf, wenn der Thread gestartet wird –

+0

Verwendet [thread-> SetApartment] (https://github.com/dotnet/coreclr/blob/master/src/vm/comsynchronizable.cpp#L987) 'CoInitialize () 'intern? Ich habe das STAThread-Attribut den ganzen Weg nach unten verfolgt, aber die Spur ist kalt geworden (ich kann die Quelle für 'Thread :: SetApartment' nicht finden). Ist die Thread-Klasse von thread.h (der COM-Thread.h) irgendwo dokumentiert? Ist es MFC, ATL oder etwas anderes? – jrh

-14

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