Domanda

Sono in esecuzione un servizio di Windows multithread che hanno bisogno di chiamare un DLL VB6. Non c'è alcuna documentazione su questo VB6 dll e questo sistema legacy supporta un processo di business molto critico.

In un primo tempo (1 ° filo), questa DLL si comporta bene. Come altri thread hanno bisogno di accedere, è iniziare a fornire risultati errati.

Ho letto una ragazzi dicendo:

  

"Basta essere attenti di una cosa se si utilizza VB6. Il tuo threading   modello è costretta a cambiare per appartamenti di supporto se si è   l'esecuzione di un servizio di multithread. VB supporta solo multipla   appartamenti a thread singolo, ma .NET gestisce completamente gratuito filettato   normalmente. Il filo che chiama in VB6 DLL deve essere   compatibile con la DLL ".

Un altro ragazzo dalla squadra mi ha dato l'idea di mettere questo ddl in un dominio di applicazione separata. Ma non sono sicuro.

Come possiamo lavorare con VB6 dll chiamato da un Windows C # applicazione di servizio multithread?

È stato utile?

Soluzione

Quando i fili sono disponibili in, stai salvando oggetti e riutilizzarli in seguito nuove discussioni? Se è possibile, creare gli oggetti freschi per ogni thread. Abbiamo una situazione come questa, con una dll livello di dati che utilizziamo. Se si crea una connessione su un filo, non può essere utilizzato da un altro. Se si crea una nuova connessione su ogni filo, funziona benissimo.

Se è lento per creare i vostri oggetti, guardare la classe ThreadPool e l'attributo ThreadStatic. Threadpools riciclare lo stesso insieme di fili più e più volte per fare il lavoro, e ThreadStatic consente di creare un oggetto che esiste per un solo thread. ad esempio

[ThreadStatic]
public static LegacyComObject myObject;

Come arriva una richiesta, trasformarlo in un lavoro e la coda nel vostro pool di thread. Quando il processo viene avviato, controllare se l'oggetto statico viene inizializzato;

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

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

Altri suggerimenti

Dici

  

Sono in esecuzione un Windows multithread   servizio che hanno bisogno di chiamare un DLL VB6.   Non c'è alcuna documentazione su questo   VB6 dll e questo sistema legacy   sostiene un business molto critica   processo.

e allo stesso tempo si dice

  

In un primo tempo (1º filo), questa DLL   si comporta bene. Come altri thread devono   l'accesso, si avvia fornire sbagliato   risultati.

mi piacerebbe fare molto certo che la gestione è a conoscenza del fallimento si sta vedendo, perché il codice di sostenere il processo di business critical è vecchio e non documentata, e viene utilizzato in un modo che non è mai stato destinato ad essere utilizzato, ed era mai testato per essere utilizzato. Scommetto che è anche mai stato testato per essere utilizzato da .NET prima, l'ha?

Ecco il mio consiglio, e questo è simile a qualcosa che ho effettivamente implementato:

Il VB6 DLL si aspetta di essere chiamato su un singolo filo. Non deludere esso! Quando il servizio viene avviato, avere avvio un filo del tipo appropriato (non posso dire, dal momento che ho volutamente dimenticato tutto quello che STA / MTA roba). In coda le richieste a quel filo per l'accesso al VB6 DLL. Hanno tutti tale accesso passare attraverso il singolo thread.

In questo modo, per quanto riguarda la DLL VB6 è interessato, è in esecuzione esattamente come è stato testato per funzionare.


A proposito, questo è un po 'diverso da quello che ho implementato. Ho avuto un servizio web, non è un servizio di Windows. Ho avuto un C DLL, non VB6, e non era COM. Ho appena refactoring tutti gli accessi alla cosa in una singola classe, poi mettere le dichiarazioni di blocco intorno a ciascuno dei metodi pubblici.

questo articolo sul multithreading di Visual Basic 6 DLL fornisce una certa comprensione. Dice:

  

Per fare un progetto DLL ActiveX   multithreaded, selezionare il desiderato   opzioni di filettatura nella scheda Generale   della finestra di dialogo Proprietà progetto.

Questo articolo dice che ci sono tre possibili modelli tra cui scegliere:

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

Si considera che il default è one thread of execution, e che una delle altre due opzioni deve essere selezionato.

Si potrebbe voler dare un'occhiata a questo: linky

E qui è un frammento che ha attirato la mia attenzione:

  

oggetti VB6 COM sono oggetti STA, che significa che devono funzionare su un thread STA.   È stato creato due istanze dell'oggetto da due thread MTA, ma l'oggetto stesso verrà eseguito su un unico (COM (OLE) creato) STA   filo, e l'accesso dai due thread MTA verranno marshalling e sincronizzati.   Quindi, ciò che si dovrebbe fare è, inizializzare i thread come STA in modo che ogni oggetto viene eseguito in proprio thread STA senza marshalling e si   andrà bene.

     

In ogni caso, VB oggetti COM stile sono sempre STA. Ora, al fine di prevenire appartamento marshalling e filo di commutazione è necessario creare   casi in STA inizializzati appartamenti.   Si noti inoltre che quando si imposta l'attributo [MTAThread] on Main, si inizializza in modo efficace il thread principale come MTA, quando si crea   istanze di oggetti STA dal thread MTA COM crea un thread separato (non gestito) e inizializzate come STA (questo è chiamato il   predefinito STA), tutte le chiamate agli oggetti STA dal thread MTA saranno marshalling (e incorrere interruttori filo), in alcuni casi chiamate IDispatch   non riuscirà a causa di errori di marshalling IP.   Così il consiglio è uso STA (e quindi VB6) oggetti da appartamenti compatibili solo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top