2010-12-25 10 views
17

Wenn wir eine Thread-STA wie folgt machen: Thread.SetApartmentState(STA); dann kann es Code mit [MTAThread] Attribut nicht ausgeführt ausführen.Was sind die Einschränkungen eines STA-Threads im Vergleich zu MTA-Threads?

Wir haben gesehen [STAThread] in Windows und Konsolenanwendungen, aber ich habe nie Code mit [MTAThread] Attribut gesehen und weiß nicht, welche .NET-Bibliotheken dieses Attribut verwenden.

Meine Frage ist, was sind die Beschränkungen eines Threads mit Appartment State auf STA, im Vergleich zu Threads mit MTA Appartment-Status (natürliche .NET-Threads)?

Antwort

18

Dann kann Code nicht ausgeführt werden, der mit [MTAThread] -Attribut markiert ist.

So funktioniert das nicht. Der Wohnungstyp ist eine Eigenschaft eines Threads, nicht einer Methode. Das Attribut [STAThread] wird nur auf die Main() - Methode eines .NET-Programms angewendet. Es bestimmt den Wohnungstyp des ersten Threads, der zum Ausführen des Programms erstellt wird. Dies ist erforderlich, da Sie SetApartmentState() nicht aufrufen können, nachdem der Thread ausgeführt wurde. Darüber hinaus hat das Attribut keine Bedeutung, der Thread bleibt während seiner Lebensdauer in einer STA. Sie sehen [MTAThread] nicht, da dies der Standardwert ist.

Ein Thread, der STA ist, hat einige Einschränkungen. Es kann niemals blockieren, da dies jeden Code blockiert und häufig blockiert, der versucht, eine Methode eines Apartment-Threaded-COM-Objekts aufzurufen. Und es muss eine Nachrichtenschleife pumpen, damit COM den Methodenaufruf von einem anderen Thread marshallen kann. Marshalled-Methodenaufrufe können nur ausgeführt werden, wenn ein Thread "inaktiv" ist und nicht mit der Ausführung von Code beschäftigt ist. Eine Nachrichtenschleife stellt den Zustand "nicht besetzt" bereit.

Es gibt Anforderungen an die COM-Komponente. Es muss das Marshalling unterstützen, indem es sich entweder auf die Teilmenge von Typen beschränkt, die von der Automatisierung unterstützt werden, so dass der Standard-Marshaller verwendet werden kann. Oder indem Sie ein Proxy/Stub-Paar für das benutzerdefinierte Marshalling bereitstellen. Der Registrierungsschlüssel bestimmt, wie das Marshalling durchgeführt wird.

Das Teilen eines Apartment-Thread-Objekts zwischen einem STA- und einem MTA-Thread wird explizit unterstützt. Der STA-Thread muss es erstellen, alle Aufrufe auf dem MTA-Thread (oder anderen STA-Threads) werden gemarshallt. Dies stellt sicher, dass die Komponente immer nur Aufrufe auf demselben Thread sieht, wodurch die Thread-Sicherheit gewährleistet wird. Es ist keine zusätzliche Verriegelung erforderlich.

Last but not least, wenn Sie eine Wohnung Thread-COM-Objekt auf einem MTA-Thread erstellen dann COM wird ein STA-Thread automatisch erstellen sie ein sicheres Zuhause zu geben. Der einzige Fehlermodus dafür ist, wenn die COM-Komponente Marshalling nicht unterstützt. Der einzige Nachteil dabei ist, dass jeder Aufruf gemarshallt wird. Das ist langsam.

+2

MTAThread ist nur Standard in C#. In vb.net ist STAThread der Standard. Nur zu sagen ... weil diese mir dauerte eine ganze Weile – DanielG

+0

, um herauszufinden, dass für ein VB.NET Konsolenmodus Projekt genau ist. Grobe Verletzung der STA-Anforderungen btw, ein STA-Thread muss pumpen.VB-Programmierer haben nie viel Glück beim Schreiben von Thread-Code, die Standardinstanz einer Form-Klasse ist ein weiterer wichtiger Trap. Vielleicht war das alles absichtlich :) –

0

Ich glaube nicht, dass es einen Unterschied macht, wenn Sie nicht COM verwenden. Wenn Sie dies tun, sind COM-Objekte möglicherweise nur von einem oder einem anderen Threadtyp aus zugänglich. Wenn das COM-Objekt in beiden Apartments funktioniert, führen Sie Leistungstests durch. Oder lesen Sie über COM Apartments auf MSDN. Aber ich denke nicht, dass es für die Leistung wichtig ist, es ist eher eine Design-Wahl oder etwas.

+0

Ich benutze 'COM' Komponenten und brauchen' STA'. Wechselnde Wohnung Zustand tun, was ich brauche. Ich bin mir nicht sicher über die Konsequenzen. Ein 'STA'-Thread und ein' MTA'-Thread teilen sich ein Objekt innerhalb einer 'ASP.NET'-Anwendung. – Xaqron