Rufen Sie VB6 DLL von einem Multithreaded C # -Windows-Service-Anwendung?
-
22-08-2019 - |
Frage
Ich bin mit einer Multi-Thread-Windows-Dienst, der eine VB6-DLL aufrufen müssen. Es gibt keine Dokumentation zu diesem VB6 DLL und das Legacy-System unterstützt einen sehr kritischen Geschäftsprozess.
Auf den ersten Zeit (1 Thread), führt diese dll gut. Wie andere Threads zugreifen müssen, starten Sie es falsch Ergebnisse liefern.
Ich lese ein Jungs sagen:
"vorsichtig sein, nur an einer Sache, wenn Sie VB6 verwenden. Ihr Threading Modell wird zu Unterstützung Wohnungen ändern müssen, wenn Sie sind Betrieb eines Multi-Thread-Service. VB unterstützt nur mehr Single-Threaded-Wohnungen, aber .NET läuft völlig frei Gewinde normalerweise. Der Faden, der in die VB6 DLL aufruft muss sein kompatibel mit dem DLL. "
Ein weiterer Mann vom Team gab mir die Idee, diese ddl in einem separaten Anwendungsdomäne zu setzen. Aber ich bin nicht sicher.
Wie können wir mit VB6 DLL arbeiten von einem Multithreaded C # Windows-Dienst-Anwendung aufgerufen?
Lösung
Wenn die Fäden in, speichern Sie Objekte und sie später auf neue Themen Wiederverwendung? Wenn Sie können, erstellen Sie die Objekte frisch für jeden Thread. Wir haben eine Situation wie diese mit einer Datenschicht dll wir verwenden. Wenn Sie eine Verbindung auf einem Thread erstellen, kann es nicht von anderen verwendet werden. Wenn Sie eine neue Verbindung auf jedem Thread erstellen, es funktioniert gut.
Wenn es langsam ist Ihre Objekte zu erstellen, Blick auf die Klasse Threadpool und dem Threadstatic-Attribut. Threadpools recyceln den gleichen Satz von Fäden über und über die Arbeit zu tun, und Threadstatic können Sie ein Objekt erstellen, die nur für einen Thread existiert. zB
[ThreadStatic]
public static LegacyComObject myObject;
Als eine Anforderung kommt, schalten Sie ihn in einen Job und Warteschlange es in Ihrem Thread-Pool. Wenn der Job gestartet wird, prüfen, ob das statische Objekt initialisiert wird;
void DoWork()
{
if (myObject == null)
{
// slow intialisation process
myObject = New ...
}
// now do the work against myObject
myObject.DoGreatStuff();
}
Andere Tipps
Sie sagen
Ich bin mit einem Multithread-Fenster Service, der eine VB6-DLL aufrufen müssen. Es gibt keine Dokumentation darüber VB6-DLL und dieses Legacy-System unterstützt ein sehr wichtiges Geschäft Prozess.
und zugleich Sie sagen,
Beim ersten Mal (1e Gewinde), hält diese dll funktioniert gut. Wie andere Threads müssen Zugang, starten Sie es falsch liefern Ergebnisse.
Ich würde sehr sicher, dass das Management bewusst das Scheitern ist, dass Sie zu sehen sind, da der Code den kritischen Geschäftsprozess unterstützen alt und ohne Papiere ist, und in einer Art und Weise verwendet wird, um es nie verwendet werden sollte, und war nie verwendet werden, getestet. Ich wette, es ist auch noch nie von .NET verwendet wird getestet, oder?
Hier ist mein Vorschlag, und das ist ähnlich wie etwas, das ich tatsächlich umgesetzt haben:
Die VB6 DLL erwartet auf einem einzigen Thread aufgerufen werden. Enttäusche es nicht! Wenn Ihr Dienst gestartet wird, haben sie einen Thread des entsprechenden Typs starten (Ich kann nicht sagen, da ich bewusst alles, was STA vergessen haben / MTA Sachen). Warteschlange Anfragen an diesen Thread für den Zugang zum VB6 DLL. gehen alle haben diesen Zugang durch den einzigen Thread.
Auf diese Weise, so weit das VB6 DLL betrifft, so läuft es genau so, wie es ausgeführt wurde getestet, um.
BTW, das ist etwas anderes, als was ich umgesetzt habe. Ich hatte einen Web-Service, kein Windows-Dienst. Ich hatte eine C-DLL, nicht VB6, und es war nicht COM. Ich Refactoring nur alle Zugriff auf die Sache zu einer einzigen Klasse, dann setzen Sperre Aussagen um jede der öffentlichen Methoden.
dieser Artikel auf Multithreading Visual Basic 6 DLL bietet einen kleinen Einblick. Dort heißt es:
Um ein ActiveX-DLL-Projekt zu machen multithreaded, wählen die gewünschte Optionen auf dem Registerkarte Allgemein Einfädeln des Dialogfelds Projekteigenschaften.
diesem Artikel es sagt sind drei mögliche Modelle zur Auswahl:
One thread of execution
Thread pool with round-robin thread assignment
Every externally created object is on its own thread
Ich gehe davon aus, dass die Standard one thread of execution
ist, und dass eine der beiden anderen Optionen muss ausgewählt werden.
Sie können einen Blick auf diese nehmen wollen: linky
Und hier ist ein Ausschnitt, das meine Aufmerksamkeit erregte:
VB6 COM-Objekte sind STA-Objekte, das heißt, sie auf einem STA-Thread ausgeführt werden müssen. Sie haben zwei Instanzen des Objekts von zwei MTA-Threads erstellen, aber das Objekt selbst wird auf einem einzigen (KOM (OLE) erstellt) STA läuft Faden, und den Zugang von den beiden MTA Threads gemarshallte und synchronisiert werden. Also, was Sie tun sollten, ist, die Fäden als STA initialisiert werden, so dass jede Objekte auf seinem eigenen STA-Thread läuft ohne Serialisieren und Sie wird gut.
Wie auch immer, VB Stil COM-Objekte sind immer STA. Um nun zu verhindern Wohnung Serialisieren und fädeln Schalt Sie erstellen müssen Instanzen in STA initialisiert Wohnungen. Beachten Sie auch, dass, wenn Sie die Option [MTAThread] -Attribut auf Main, Sie effektiv den Haupt-Thread als MTA initialisieren, wenn Sie erstellen Instanzen von STA-Objekten aus MTA Threads COM wird ein separates (nicht verwalteten) Gewinde erstellen und als STA initialisiert wird (dies die aufgerufen wird, Standard-STA), werden alle Anrufe an STA Objekte aus MTA Threads werden gemarshallte (und Faden Schalter anfallen), in einigen Fällen Anrufe Idispatch wird aufgrund von IP Serialisieren Ausfälle ausfallen. So ist die Beratung ist die Verwendung STA (und damit VB6) Objekte von kompatibelen Wohnungen nur.