Llamar VB6 DLL de una aplicación de servicio de Windows en C # multiproceso?
-
22-08-2019 - |
Pregunta
Estoy corriendo un servicio de Windows multiproceso que necesita llamar a una DLL de VB6. No hay documentación sobre este DLL VB6 y este sistema heredado es compatible con un proceso de negocio muy crítico.
A primera hora (primera rosca), esta DLL realiza bien. Como otros hilos necesitan tener acceso, se inicia proporcionar resultados erróneos.
leí uno chicos que dicen:
"Sólo tenga cuidado de una cosa si está utilizando Visual Basic 6. Su enhebrado modelo se va a tener que cambiar a apartamentos de asistencia Si tiene la ejecución de un servicio de multiproceso. VB sólo es compatible con múltiples apartamentos de un único subproceso, pero .NET se ejecuta totalmente libre de roscado normalmente. El subproceso que llama a la DLL de VB6 tiene que ser compatible con la DLL ".
Otro tipo de equipo me dio la idea de poner este DDL en un dominio de aplicación separada. Pero no estoy seguro.
¿Cómo podemos trabajar con VB6 DLL llamada desde una aplicación de servicio de Windows en C # multiproceso?
Solución
Cuando los hilos entran, está ahorrando objetos y reutilizarlos más adelante nuevos temas? Si es posible, crear los nuevos objetos para cada hilo. Tenemos una situación como esta con un DLL capa de datos que utilizamos. Si crea una conexión en un hilo, no puede ser utilizado de otra. Si crea una nueva conexión en cada hilo, que trabaja muy bien.
Si es lento para crear sus objetos, mirar a la clase ThreadPool y el atributo ThreadStatic. Threadpools reciclan el mismo conjunto de hilos y otra vez para hacer el trabajo, y ThreadStatic le permite crear un objeto que existe para un solo hilo. por ejemplo,
[ThreadStatic]
public static LegacyComObject myObject;
A medida que llega una petición, lo convierten en un trabajo y hacer cola en su grupo de subprocesos. Cuando se inicia el trabajo, comprobar si el objeto estático se inicializa;
void DoWork()
{
if (myObject == null)
{
// slow intialisation process
myObject = New ...
}
// now do the work against myObject
myObject.DoGreatStuff();
}
Otros consejos
Usted dice
Estoy corriendo una ventana multiproceso servicio que necesita llamar a una DLL de VB6. No hay documentación sobre este DLL VB6 y este sistema heredado soporta un negocio muy crítico proceso.
y, al mismo tiempo que dice
A primera tiempo (1º hilo), esta DLL funciona bien. Como otros hilos necesitan acceso, se inicia proporcionar equivocada resultados.
Me gustaría hacer muy seguro de que la administración es consciente de la falla que se está viendo ya que el código de apoyo al proceso de negocio crítico es viejo y no documentada, y está siendo utilizado de una manera que nunca fue pensado para ser utilizado, y estaba Nunca probado para ser utilizado. Apuesto a que nunca es también ha sido probado para ser utilizado desde .NET antes, ¿verdad?
Aquí está mi sugerencia, y esto es similar a algo que he implementado en realidad:
El VB6 DLL espera ser llamada en un solo hilo. No decepcionar a él! Cuando el servicio se inicia, hacer que se inicie un hilo del tipo apropiado (no puedo decir, ya que se me ha olvidado deliberadamente todo lo que STA / MTA cosas). Poner en cola las peticiones a ese hilo de acceso a la DLL de VB6. Todos han dicho acceso pasar por el solo hilo.
De este modo, en lo que se refiere a la DLL de VB6, que está funcionando exactamente como fue probado para funcionar.
Por cierto, esto es ligeramente diferente de lo que he implementado. Tenía un servicio web, no un servicio de Windows. Tenía una DLL de C, no VB6, y no era COM. Yo sólo refactorizado todos los accesos a la cosa en una sola clase, a continuación, poner las declaraciones de bloqueo alrededor de cada uno de los métodos públicos.
Este artículo sobre multithreading de Visual Basic 6 DLL proporciona una cierta penetración. Dice:
Para realizar un proyecto DLL ActiveX multiproceso, seleccionar el deseado enhebrar opciones en la ficha General del cuadro de diálogo Propiedades del proyecto.
Este artículo dice que hay tres posibles modelos para elegir:
One thread of execution
Thread pool with round-robin thread assignment
Every externally created object is on its own thread
Asumo que el valor predeterminado es one thread of execution
, y que una de las otras dos opciones se debe seleccionar.
Es posible que desee echar un vistazo a esto: Linky
Y aquí es un fragmento que me llamó la atención:
Los objetos COM VB6 son objetos STA, que significa que deben ejecutarse en un subproceso STA. ¿Te ha crear dos instancias del objeto a partir de dos subprocesos MTA, pero el propio objeto se ejecutará en un único (COM (OLE) creado) STA hilo, y el acceso desde los dos hilos de MTA se calculan y sincronizados. Así que lo que debe hacer es, inicializar los hilos como STA modo que cada objeto se ejecuta en su propio subproceso STA sin cálculo de referencias y va a estar bien.
De todos modos, VB objetos COM estilo son siempre STA. Ahora con el fin de evitar que el cálculo de referencias de apartamentos y el hilo de conmutación es necesario crear casos en STA inicializan apartamentos. Tenga en cuenta también que cuando se establece el atributo [MTAThread] en Main, inicializar efectivamente el hilo principal como MTA, cuando se crea casos de STA objetos de subprocesos MTA COM va a crear un hilo separado (no administrada) y inicializarlo como STA (esto se denomina la predeterminado STA), se calculan todas las llamadas a objetos STA de subprocesos MTA (e incurrir en interruptores de rosca), en algunos casos IDispatch llamadas fallará debido a fallas en el cálculo de referencias IP. Así que el consejo es el uso STA (y por lo tanto, Visual Basic 6) objetos de apartamentos compatibles solamente.