Pergunta

I têm uma aplicação de um C # (FFx 3,5) que carrega os DLLs como plug-ins. Esses plug-ins são carregados em AppDomains separados (para os lotes de boas razões, e essa arquitetura não pode mudar). Isto é tudo muito bem.

Agora tenho um requisito para mostrar um diálogo de um desses plug-ins. Tenha em mente que eu não pode devolver o Formulário de diálogo para a aplicação principal e apresentá-lo lá (a infra-estrutura atual não suporta-lo).

Falha 1

Na minha DLL Eu criei um formulário e chamou Show. O esboço de diálogo apareceu, mas não pintar e ele não responde a eventos do mouse. Eu assumi que este é becasue a DLL está em um AppDomain separado e a bomba de mensagem para o aplicativo de alguma forma é incapaz de distribuir mensagens para a nova forma.

Falha 2

Na minha DLL Eu criei um formulário e chamou ShowDialog, que por todos os direitos devem criar uma bomba de mensagem interna para o diálogo .. O diálogo é exibida e respondeu a cliques (hooray), mas parece que o aplicativo principal não está processando ou despachar mensagens do Windows porque ele sai pintura e já não responde a eventos do mouse. Por alguma razão, agora parece que bomba de mensagem do aplicativo principal não está despachando.

A falha 3

Na minha DLL Eu criei um formulário e chamou Application.Run. Isso certamente vai criar uma bomba mensagem completa segundo. Eu obter o mesmo comportamento como falha. 2 - se comporta de diálogo, mas o aplicativo de chamada não

Quaisquer pensamentos sobre o que exatamente está acontecendo aqui e como eu poderia ir sobre apresentação de uma janela de DLL do outro AppDomain e ambos têm o chamador eo receptor ainda respondem e pintar corretamente?

Foi útil?

Solução

Tente usar BeginInvoke principal do formulário de appdomain1 com um delegado que exibe a forma de appdomain2. Assim, em Pseudocódigo:

Appdomain1:
    AppDomain2.DoSomething(myMainForm);

AppDomain2:
    DoSomething(Form parent)
    {
        Form foolishForm = new Form();
        parent.BeginInvoke(new Action( delegate { foolishForm.Show(); } ));
    }

O código não pode ser perfeito, mas demonstra o conceito.

A propósito, se você está tendo problemas para passar as formas ao redor por causa de comunicação remota, você pode:

public class Container<T> : MarshalByRefObject
{
    private T _value;
    public T Value { get { return _value; } set { _value = value; } }

    public Container() { }
    public Container(T value) { Value = value; }

    public static implicit operator T(Container<T> container)
    {
        return container.Value;
    }
}

que conterá objeto que você jogue com ele.

Outras dicas

Nós temos uma aplicação muito semelhante arquitetado que carrega a DLL arquivos e plugins. Cada arquivo DLL é carregada em um domínio de aplicação, que é criado em um segmento separado. Nós temos um controle de terceiros de uma forma que não iria aparecer a menos que chamamos System.Windows.Forms.Application.DoEvents() regularmente.

código Pseudo:

<In new thread>
  <Application domain created. Start called inside new application domain.>
  <Start loads new DLL file, calls init function in DLL file>
  <Start loops, calling DoEvents until the DLL file exits>
  <Application domain unloaded>
<Thread exits>

Este resolvido todos os nossos problemas GUI.

Uma coisa que eu usei antes está a implementar um DomainManager . É possível personalizar os vários aplicativo de segurança de domínio / ligação / de lidar contexto complexo ou frango de ovo digite problemas com relação a bombear seus dados onde quer;)

Eu ususally feito isso de um native.exe, bootstrapping o CLR através das interfaces COM (código psudo mas a ordem e método nomes estão corretos;):

CorBindToRuntimeEx()
SetHostControl()
GetCLRControl()
SetAppDomainManagerType("yourdomainmanger","info")
// Domain manager set before starting runtime
Start()
HostControl -- GetDomainManagerForDefaultDomain()
DomainManager -- Run()

O seu gerenciador de domínio pode ser qualquer CLR biblioteca de classes, assim que seu não é que muito mais nativa C.

Uma nota lateral, se você estivesse em WPF ; Eu realmente gosto de usar o método "Microsoft.DwayneNeed.Controls". Onde você pode ter tópicos disperate com a sua própria bomba Dispatcher no mesma controle de UI (não necessitando de recorrer a inteiramente nova janela () 's).

A única coisa sobre o uso dessa abordagem, é que mesmo que o segmento interface do usuário principal está bloqueada / ocupado (alguns operação pesada, a digitalização do sistema de arquivos, etc ...), esses outros tópicos podem pintar / atualizar seu UIElement do sem qualquer soluço .

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