Насосы сообщений и домены приложений - PullRequest
3 голосов
/ 13 января 2009

У меня есть приложение на C # (FFx 3.5), которое загружает библиотеки DLL как подключаемые модули. Эти плагины загружаются в отдельные домены приложений (по многим причинам, и эта архитектура не может измениться). Это все хорошо.

Теперь у меня есть требование показать диалог из одного из этих плагинов. Помните, что я не могу вернуть диалоговую форму в основное приложение и отобразить ее там (текущая инфраструктура ее не поддерживает).

Отказ 1

В моей DLL я создал форму и назвал Show. Контур диалога появился, но не рисовал, и он не реагирует на события мыши. Я предположил, что это потому, что DLL находится в отдельном домене приложений, а насос сообщений для приложения каким-то образом не может отправлять сообщения в новую форму.

Отказ 2

В моей DLL я создал Form и назвал ShowDialog, который по всем правам должен создать внутреннюю рассылку сообщений для диалога. Диалог отображается и реагирует на щелчки (ура), но кажется, что основное приложение больше не обрабатывает или отправляет сообщения Windows, потому что он прекращает рисование и больше не реагирует на события мыши. По какой-то причине теперь кажется, что насос сообщений основного приложения не отправляет.

Отказ 3

В моей DLL я создал Form и назвал Application.Run. Это, безусловно, создаст полный второй насос сообщений. Я получаю то же поведение, что и Failure 2 - диалоговое окно ведет себя, но вызывающее приложение - нет.

Есть какие-нибудь мысли о том, что именно здесь происходит, и как я мог бы показать диалоговое окно из библиотеки DLL другого AppDomain, чтобы и вызывающий, и вызываемый все еще отвечали и рисовали правильно?

Ответы [ 3 ]

4 голосов
/ 14 января 2009

Попробуйте использовать BeginInvoke главной формы appdomain1 с делегатом, который отображает форму из appdomain2. Так в псевдокоде:

Appdomain1:
    AppDomain2.DoSomething(myMainForm);

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

Код может быть не идеальным, но он демонстрирует концепцию.

Кстати, если у вас возникли проблемы с передачей форм из-за удаленного взаимодействия, вы можете:

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;
    }
}

Это будет содержать объект, который вы бросаете в него.

1 голос
/ 29 мая 2009

Одна вещь, которую я использовал раньше, это реализация DomainManager . Можно настроить различные прикладные домены security /inding / context для обработки сложных проблем или проблем типа куриного яйца в отношении перекачки ваших данных туда, куда вы хотите;)

Я обычно делал это из native.exe, загружая CLR через COM-интерфейсы (псевдокод, но порядок и имена методов верны;):

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

Ваш менеджер домена может быть любой CLR библиотекой классов, так что они не намного более родные C.

Примечание, если вы были в WPF ; Мне действительно нравится использовать метод Microsoft.DwayneNeed.Controls. В тех случаях, когда у вас могут возникать проблемы с потоками с их собственным насосом Dispatcher в том же элементе управления UI (не нужно прибегать к совершенно новым Window ()).

Уникальная особенность использования этого подхода заключается в том, что даже если основной поток пользовательского интерфейса заблокирован / занят (некоторые тяжелые операции, сканирование файловой системы и т. Д.), Эти другие потоки могут рисовать / обновлять свои элементы UIElement без какого-либо сбоя .

1 голос
/ 19 апреля 2009

У нас очень похожее приложение, которое загружает DLL-файлы и плагины. Каждый файл DLL загружается в отдельный домен приложения , который создается в отдельном потоке. У нас есть сторонний контроль в форме, которая не появится, если мы не будем регулярно звонить System.Windows.Forms.Application.DoEvents().

Псевдокод:

<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>

Это решило все наши проблемы с графическим интерфейсом.

...