Question

Je suis en cours d'exécution d'un service Windows multithread qui ont besoin d'appeler une dll VB6. Il n'y a pas de documentation sur ce dll VB6 et ce système existant prend en charge un processus métier très critique.

À première fois (1er fil), ce dll donne de bons résultats. Comme d'autres discussions doivent avoir accès, il commence de fournir des résultats erronés.

Je lis un gars en disant:

  

"Faites juste attention d'une chose si vous utilisez VB6. Votre filetage   modèle va devoir changer d'appartements de soutien si vous êtes   exécution d'un service multithread. VB prend uniquement en charge multiple   appartements mono-thread, mais .NET fonctionne de manière entièrement libre filetée   normalement. Le thread qui appelle dans la VB6 DLL doit être   compatible avec la DLL. "

Un autre gars de l'équipe m'a donné l'idée de mettre ce ddl dans un domaine d'application séparée. Mais je ne suis pas sûr.

Comment peut-on travailler avec dll VB6 appelé à partir d'une fenêtre multithread c # application de service?

Était-ce utile?

La solution

Quand les fils viennent, vous les objets et les réutiliser économiserez plus tard sur les nouvelles discussions? Si vous pouvez, créer les nouveaux objets pour chaque fil. Nous avons une telle situation, avec une dll couche de données que nous utilisons. Si vous créez une connexion sur un fil, il ne peut pas être utilisé d'une autre. Si vous créez une nouvelle connexion sur chaque fil, il fonctionne très bien.

S'il est lent à créer vos objets, regardez la classe ThreadPool et l'attribut ThreadStatic. Threadpools recycler le même ensemble de fils à plusieurs reprises pour faire le travail, et ThreadStatic vous permet de créer un objet qui existe pour un seul fil. par exemple,

[ThreadStatic]
public static LegacyComObject myObject;

En tant que requête arrive, le transformer en un emploi et la file d'attente dans votre pool de threads. Lorsque le travail commence, vérifier si l'objet statique est initialisée;

void DoWork()
{ 
    if (myObject == null)
    { 
        // slow intialisation process
        myObject = New ...
    }

    // now do the work against myObject
    myObject.DoGreatStuff();
}

Autres conseils

Vous dites

  

Je suis en une fenêtre multithread   services qui ont besoin d'appeler une dll VB6.   Il n'y a pas de documentation à ce sujet   dll VB6 et ce système d'héritage   soutient une entreprise très critique   processus.

et en même temps vous dites

  

À première fois (1º fil), ce dll   effectue bien. Comme d'autres sujets ont besoin   l'accès, il commence mal fournir   résultats.

Je ferais bien certain que la direction est au courant de l'échec que vous voyez parce que le code de soutenir le processus d'affaires critiques est vieux et sans papier, et est utilisé dans un sens, il n'a jamais été destiné à être utilisé, et était jamais testé à utiliser. Je parie que c'est également jamais été testé pour être utilisé à partir de .NET avant, a?

Voici ma suggestion, ce qui est similaire à quelque chose que j'ai effectivement mis en œuvre:

La DLL VB6 attend d'être appelé sur un seul thread. Ne pas décevoir! Lorsque votre service démarre, faites-le démarrage d'un fil du type approprié (je ne peux pas dire, depuis que je suis délibérément oublié tout ce que STA / MTA choses). Queue demande à ce fil d'accès à la VB6 DLL. Ont tous cet accès passer par le fil unique.

De cette façon, jusqu'à la DLL VB6 est concerné, il est en cours d'exécution exactement comme il a été testé pour fonctionner.


BTW, ce qui est légèrement différent de ce que j'ai mis en place. J'ai eu un service Web, et non un service Windows. J'ai eu une DLL C, pas VB6, et ce ne COM. Je viens refactorisé tous les accès à la chose dans une seule classe, puis mettre des déclarations de verrouillage autour de chacune des méthodes publiques.

Cet article sur multithreading 6 DLL Visual Basic de fournit un aperçu. Il dit:

  

Pour un projet DLL ActiveX   multithread, sélectionner le souhaite   filetage options de l'onglet Général   de la boîte de dialogue Propriétés du projet.

Cet article dit il y a trois modèles possibles au choix:

One thread of execution 
Thread pool with round-robin thread assignment 
Every externally created object is on its own thread 

Je suppose que la valeur par défaut est one thread of execution, et que l'une des deux autres options doit être sélectionnée.

Vous pouvez jeter un oeil à ceci: linky

Et voici un extrait qui a attiré mon attention:

  

objets VB6 COM sont des objets STA, cela signifie qu'ils doivent fonctionner sur un thread STA.   Vous avez créé deux instances de l'objet de deux threads MTA, mais l'objet lui-même se déroulera sur un seul (COM (OLE) créé) STA   fil, et l'accès des deux threads MTA seront marshalés et synchronisés.   Donc ce que vous devez faire est, initialiser les threads comme STA de sorte que chaque objet tourne sur son propre thread STA sans marshaling et vous   sera très bien.

     

Quoi qu'il en soit, les objets COM VB de style sont toujours STA. Maintenant, afin d'éviter appartement marshaling et le fil de commutation, vous devez créer   cas dans STA initialisés appartements.   Notez également que lorsque vous définissez la [MTAThread] attribut principal, vous initialisez efficacement le thread principal en tant que MTA, lorsque vous créez   instances de STA objets de threads MTA COM crée un thread séparé (non géré) et l'initialiser comme STA (ce qui est appelé   par défaut STA), tous les appels vers des objets STA de threads MTA seront marshalés (et engager des interrupteurs de fil), dans certains cas, appels IDispatch   échouera en raison de défaillances de marshaling IP.   Ainsi, le conseil est d'utiliser STA (et donc VB6) objets d'appartements compatibles uniquement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top