Pergunta

Aqui está o problema central: Eu tenho um aplicativo .NET que está usando interoperabilidade em um separar domínio de aplicação. O material COM parece ser montagens de carga de volta para o domínio padrão, ao invés do AppDomain a partir do qual o material COM está sendo chamado.

O que eu quero saber é: é esse comportamento esperado, ou estou fazendo algo errado para causar estes conjuntos relacionados COM a ser carregados no AppDomain errado? Por favor, veja uma descrição mais detalhada da situação abaixo ...

A aplicação consiste em 3 conjuntos: - o EXE principal, o ponto de entrada do aplicativo. - common.dll, contendo apenas uma IController de interface (no estilo IPlugin) - controller.dll, contendo uma classe Controller que implementos IController e MarshalByRefObject. Esta classe faz todo o trabalho e usos de interoperabilidade COM para interagir com outra aplicação.

A parte relevante dos principais olhares EXE assim:

AppDomain controller_domain = AppDomain.CreateDomain("Controller Domain");
IController c = (IController)controller_domain.CreateInstanceFromAndUnwrap("controller.dll", "MyNamespace.Controller");
result = c.Run();
AppDomain.Unload(controller_domain);

O common.dll contém apenas esses 2 coisas:

public enum ControllerRunResult{FatalError, Finished, NonFatalError, NotRun}
public interface IController
{
    ControllerRunResult Run();
}

E o controller.dll contém essa classe (que também chama o material de interoperabilidade COM):

public class Controller: IController, MarshalByRefObject

Quando a primeira execução da aplicação, Assembly.GetAssemblies () procura como esperado, com common.dll sendo carregados em ambas as AppDomains, e controller.dll única de serem carregados para o domínio controlador. Depois de chamar c.Run () no entanto eu vejo que as assembleias relacionadas com o material de interoperabilidade foram carregados para o padrão AppDomain, e não no domínio de aplicação a partir do qual o interoperabilidade COM está ocorrendo.

Por que isso pode estar ocorrendo?

E se você estiver interessado, aqui está um pouco de fundo:

Originalmente esta era uma aplicação 1 AppDomain. O material COM ele interage com uma API de servidor que não é estável durante longos períodos de uso. Quando um COMException (sem informações de diagnóstico útil quanto à sua causa) ocorre a partir do material COM, o aplicativo inteiro tem para reiniciado antes que a conexão COM irá funcionar novamente. Basta reconectar com os resultados de servidores de aplicativos COM em exceções COM imediatos novamente. Para lidar com este Tentei mover o material de interoperabilidade em um AppDomain separado para que, quando os COMExceptions mistério ocorrer posso descarregar o AppDomain em que ocorre, criar um novo e começar de novo, tudo isso sem ter que reiniciar manualmente o aplicativo . Essa era a teoria de qualquer maneira ...

Foi útil?

Solução

Infelizmente, o componente A COM é carregado no âmbito do Processo espaço e não no contexto de um domínio de aplicação. Assim, você terá que manualmente lágrima-down (lançamento e Unload) suas DLLs nativos (aplica-se tanto COM e P / Invoke). Simplesmente destruir um appdomain vai fazer você não é bom, mas respawning todo o processo não deve ser necessário para repor estado COM (simplesmente recriar o objeto COM (s) também deve normalmente trabalho, isso soa como um bug no código fornecedores de componentes, talvez eles podem dirigir-se?)

Referências

(TechNet) espaço de processo Endereço

(MSDN) Domínios de aplicação

(MSDN) Limites: Processos e AppDomains

Outras dicas

Aqui está a prova de que a resposta de Shaun Wilson está correto

Com App Domínio

Não faça seu controlador MBR. Criar uma pequena proxy, que carrega o controlador no segundo domínio e começa-lo. Dessa forma Controlador dll não será carregado no primeiro domínio.

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