Pergunta

Estou executando um serviço de janelas de vários segmentos que precisa chamar um dll VB6. Não há documentação sobre isso dll VB6 e este sistema legado suporta um processo de negócio muito crítico.

Na primeira vez (1ª linha), este dll executa bem. Como outros tópicos precisam de acesso, ele começar a fornecer resultados errados.

Eu li um caras dizendo:

"Só tome cuidado de uma coisa se você estiver usando VB6. Seu rosqueamento modelo vai ter que mudar para apartamentos de apoio se você está executando um serviço de vários segmentos. VB só suporta múltiplos apartamentos single-threaded, mas .NET corre rosca completamente livre normalmente. O segmento que chama o VB6 DLL precisa ser compatível com o DLL. "

Outra cara da equipe me deu a idéia de colocar este ddl num domínio de aplicação separada. Mas eu não tenho certeza.

Como podemos trabalhar com VB6 DLL chamado de um aplicativo de serviço c # windows multithreaded?

Foi útil?

Solução

Quando os tópicos entrar, você está salvando objetos e reutilizando-los mais tarde em novos segmentos? Se você puder, criar os objetos de fresco para cada segmento. Nós temos uma situação como esta com uma dll camada de dados que usamos. Se você criar uma conexão em um segmento, ele não pode ser usado a partir de outro. Se você criar uma nova conexão em cada segmento, ele funciona bem.

Se ele é lento para criar seus objetos, olhar para a classe ThreadPool eo atributo ThreadStatic. Threadpools reciclar o mesmo conjunto de tópicos mais e mais para fazer o trabalho, e ThreadStatic permite criar um objeto que existe para apenas um segmento. eg

[ThreadStatic]
public static LegacyComObject myObject;

Como um pedido chega, transformá-lo em um trabalho e fila-lo em seu pool de threads. Quando os começos de trabalho, verifique se o objeto estático é inicializado;

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

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

Outras dicas

Você diz

Estou executando uma janelas de vários segmentos serviço que precisa chamar um dll VB6. Não há documentação sobre isso VB6 DLL e este sistema legado suporta um negócio muito crítica processo.

e, ao mesmo tempo que você diz

Na primeira vez (1º segmento), este dll tem um bom desempenho. Como outros tópicos necessidade acesso, ele começar a fornecer errado resultados.

Eu faria muito certo que a Administração está ciente da falha que você está vendo, porque o código de suporte a processos críticos de negócio é velho e não documentados, e está sendo usado de uma forma que nunca foi destinado a ser utilizado, e foi Nunca testado para ser utilizado. Aposto que é também nunca foi testado para ser usado a partir .NET antes, não é?

Aqui está a minha sugestão, e este é semelhante a algo que eu realmente implementadas:

O VB6 DLL espera ser chamado em um único segmento. não decepciona-lo! Quando seus início do serviço, tê-lo arrancar um fio do tipo adequado (Não posso dizer que, desde que eu deliberadamente esquecido tudo o que STA / stuff MTA). Fila pedidos para esse segmento de acesso à VB6 DLL. Ter todas essas go acesso através do único segmento.

Assim, na medida em que a DLL VB6 está em causa, ele está funcionando exatamente como ele foi testado para ser executado.


BTW, este é um pouco diferente do que eu tenho implementado. Eu tinha um serviço de web, não é um serviço do Windows. Eu tinha um C DLL, não VB6, e não era COM. Eu só reformulado todo o acesso à coisa em uma única classe, instruções de bloqueio, em seguida, colocar em torno de cada um dos métodos públicos.

Este artigo sobre multithreading do Visual Basic 6 DLL fornece algumas dicas. Ele diz:

Para fazer um projeto ActiveX DLL de vários segmentos, seleccionar o desejado enfiando opções na guia Geral das propriedades do projeto caixa de diálogo.

Este artigo diz que há três possíveis modelos para escolher:

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

Eu assumo que o padrão é one thread of execution, e que uma das outras duas necessidades opções a serem selecionadas.

Você pode querer dar uma olhada nisso: linky

E aqui está um trecho que me chamou a atenção:

VB6 COM objetos são STA objetos, isso significa que eles devem ser executados em um segmento STA. Você criou duas instâncias do objeto de duas threads MTA, mas o próprio objeto será executado em um único (COM (OLE) criado) STA rosca, e o acesso a partir dos dois segmentos MTA irão ser empacotado e sincronizado. Então, o que você deve fazer é, inicializar os tópicos como STA para que cada objetos é executado em seu próprio thread STA sem empacotamento e você vai ficar bem.

De qualquer forma, VB objetos estilo COM são sempre STA. Agora, a fim de evitar apartamento empacotamento e passe a mudança que você precisa para criar casos em STA inicializado apartamentos. Note também que quando você definir o atributo [MTAThread] on Main, você efetivamente inicializar o thread principal como MTA, quando você cria instâncias de STA objetos da MTA threads COM irá criar um segmento separado (não gerenciado) e inicialize-o como STA (isso é chamado de padrão STA), todas as chamadas para STA objetos de threads MTA será empacotado (e incorrer em trocas de threads), em alguns casos, chamadas IDispatch irá falhar devido a falhas de empacotamento IP. Assim, o conselho é o uso STA (e, portanto, VB6) objetos de apartamentos compatíveis apenas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top