Frage

Stoßen, was wie eine MT-Ausgabe auf dem ersten Blick aussieht, aber ich versuche, im Detail des STA-Modell von COM + verwendet, um zu verstehen.

effektiv, ich habe ein Vermächtnis COM + -Komponente, in VB6 geschrieben, die in einen nativen nennt (das heißt nicht-COM) Win32-DLL in C ++ geschrieben.

einige intermittant (und unmöglichen in Tests zu reproduzieren) Nachdem Probleme mit sich, fügte ich einige Debug-Code, um herauszufinden, was los war und festgestellt, dass, wenn die Probleme auftreten, hatte ich Nachrichten in der Datei verschachtelt log - so es implizierte dass die DLL von zwei Threads auf einmal genannt wurde.

Jetzt geht die Protokollierung in eine Pro-Thread-Datei basierend auf _getpid () und GetCurrentThreadId (), so scheint es, dass, wenn der Code in dem C ++ DLL aufgerufen wird, wird es zweimal auf dem gleichen Thread zur gleichen Zeit immer genannt. Mein Verständnis von STA sagt schlägt dies der Fall sein könnte, wie COM die einzelnen Instanzen von Objekten auf einen einzigen Thread Marshalls aussetzt und nimmt die Ausführung nach Belieben.

Unfortuantly bin ich nicht sicher, wo man von hier geht. Ich lese, dass ich sein sollte CoInitialiseEx () in DllMain () aufrufen COM zu sagen, dass dies ein STA DLL, aber auch andere Orte sagen, dass dies für die COM-DLLs nur gültig ist und keine Wirkung in einer nativen DLL haben. Die einzige andere Möglichkeit ist es, Teile der DLL auf, als kritische Abschnitte wickeln Zugangs zur Serialisierung (was auch immer Leistungseinbußen nehmen, die auf dem Kinn).

Ich könnte versuchen, die DLL überarbeite, aber es gibt keinen gemeinsamen Staat oder globalen Vars - alles in lokalen Variablen so in der Theorie soll jeder Aufruf einen eigenen Stapel bekommen, aber ich frage mich, ob das STA-Modell ist im Grunde eine ungerade mit Einfluss auf diese und nur Wiedereintritt in die bereits geladenen DLL zur gleichen Einstiegspunkt als ein weiterer Anruf. Unfortuantly, ich weiß nicht, wie diese Theorie zu beweisen oder zu testen.

Die Fragen sind im Wesentlichen:

  1. Wenn ein STA COM + -Komponente eine native DLL aufruft, gibt es nichts in dem STA-Modell den aktiven „Faden“ verhindert, dass in der Mitte zu einem anderen „Faden“ übergegangen eines DLL-Aufruf unterbrochen und Steuerung werden?
  2. Ist CoInitialiseEx () der richtige Weg, dies oder nicht zu lösen?
  3. Wenn weder (1) oder (2) "gut" Annahmen, was los ist?
War es hilfreich?

Lösung

In einer Wohnung Thread-COM-Server, wobei jede Instanz der COM-Klasse ist garantiert durch einen einzelnen Thread-Zugriffe werden. Diese Mittel die Instanz ist Thread-sicher. Allerdings können viele Instanzen simultan erzeugt werden, verschiedene Threads verwenden. Nun, so weit wie der COM-Server betrifft, Ihre nativen DLL muss nichts Besonderes tun. Man denke nur an kernel32.dll, die von jedem ausführbar verwendet wird - ist das COM initialisieren, wenn sie von einem COM-Server verwendet

Von der DLL Sicht, müssen Sie sicherstellen, dass Sie sind Thread-sicher, da verschiedene Instanzen, die Sie in der gleichen Zeit aufrufen können. STA werden Sie nicht in diesem Fall schützen. Da Sie sagen, dass Sie keine globalen Variablen verwenden, kann ich nur annehmen, das Problem an anderer Stelle ist, und geschieht nur auf Umstände zu zeigen, die auf die COM Sachen zu zeigen scheinen. Sind Sie sicher, dass Sie nicht ein paar gute alte C ++ Speicherprobleme haben?

Andere Tipps

Ich vermute, Ihr Problem war, dass irgendwo tief innerhalb der aufgerufenen DLL, es einen ausgehenden COM-Aufruf in einer anderen Wohnung (ein anderer Thread im selben Prozess oder ein Objekt in der MTA, oder ein anderen Prozess vollständig) hergestellt. COM ermöglicht eine STA-Thread für das Ergebnis eines abgehenden Anruf wartet eine weitere eingehende Anrufe zu empfangen, es rekursiv zu verarbeiten. Es ist beabsichtigt ist nur für die laufenden Gespräche zwischen den gleichen Objekten - dh A ruft B, B A zurückruft, A ruft B wieder zurück - aber können Anrufe von anderen Objekten erhalten, wenn Sie einen Schnittstellenzeiger auf mehrere Clients verteilt haben, oder der Kunde hat die Schnittstellenzeiger auf einen anderen Client geteilt. Im Allgemeinen ist es eine schlechte Idee Schnittstellenzeiger auf ein Single-Thread-Objekt, um mehr Client-Threads, die Hand aus, als sie werden nur für sie warten. Erstellen Sie einen Arbeiter Objekt pro Thread.

COM kann nicht unterbrechen und wieder aufnehmen Ausführung nach Belieben auf jedem Thread - ein neuer Anruf auf einem STA-Thread kann nur durch die Nachricht Pumpe gelangen. Wenn ‚blockiert‘ auf eine Antwort wartet, wird der STA-Thread Nachrichten tatsächlich Pumpe, mit dem Message Filter überprüft (siehe IMessageFilter), ob die Nachricht behandelt werden soll. Nachrichten-Handler müssen jedoch keinen neuen abgehenden Anruf machen - wenn sie COM tun wird ein RPC_E_CANTCALLOUT_INEXTERNALCALL Fehler zurück ( „Es ist illegal, während im Inneren Nachrichtenfilter rufen“)

ähnliche Probleme könnten auftreten, wenn Sie innerhalb der nativen DLL eine Nachricht Pumpe (GetMessage / Dispatch) überall haben. Ich habe Probleme mit VB DoEvents in Schnittstellenverfahren hat.

CoInitializeEx sollte nur vom Schöpfer eines Thread aufgerufen werden, weil nur sie wissen, was ihre Botschaft Pumpverhalten sein. Es ist wahrscheinlich, dass, wenn Sie versuchen, es in DllMain nennen es einfach nicht, wie Sie Ihre nativen DLL in Reaktion auf einen COM-Aufruf aufgerufen wird, so dass der Anrufer schließlich bereits CoInitializeEx auf dem Thread, um den Anruf zu tätigen genannt haben muß. Tut es in der DLL_THREAD_ATTACH Benachrichtigung für neu erstellte Themen, könnte oberflächlich arbeiten, aber das Programm zu einer Fehlfunktion, wenn COM Blöcke verursachen, wenn es sollte kehrt umge pumpen und.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top