Замена процесса. Запустите с AppDomains

Я думаю, делаете ли Вы:
Окно-> Предпочтения-> Java-> Установленный JREs
Вы будете видеть список JREs на Вашей машине. Тот, который это проверяется, является тем, который использует затмение.

, С другой стороны, если Вы входите в "выполненные конфигурации" диалоговое окно и смотрите на вкладку JRE, можно выбрать JRE для работы там.

49
задан MikeWyatt 2 October 2009 в 05:12
поделиться

3 ответа

Домены приложений и междоменное взаимодействие - очень тонкий вопрос, поэтому нужно убедиться, что он действительно понимает, как все работает, прежде чем что-либо делать ... Ммм ... Скажем, "не- standard ": -)

Прежде всего, ваш метод создания потока фактически выполняется в вашем домене" по умолчанию "(сюрприз-сюрприз!). Почему? Просто: метод, который вы передаете в AppDomain.DoCallBack , определен в объекте AppDomainDelegateWrapper , и этот объект существует в вашем домене по умолчанию, так что именно здесь его метод выполняется. MSDN не говорит об этой маленькой «возможности», но ее достаточно легко проверить: просто установите точку останова в AppDomainDelegateWrapper.Invoke .

Так что, по сути, вам придется обходиться без «оболочки» "объект. Используйте статический метод для аргумента DoCallBack.

Но как передать аргумент "func" в другой домен, чтобы ваш статический метод мог взять его и выполнить?

Наиболее очевидный способ - использовать AppDomain .SetData , или вы можете свернуть свой собственный, но независимо от того, как именно вы это делаете, возникает другая проблема: если "func" - нестатический метод, то объект, для которого он определен, должен быть каким-то образом передан в другой домен приложения. Он может передаваться либо по значению (тогда как он копируется, поле за полем), либо по ссылке (создавая междоменную ссылку на объект со всей красотой удаленного взаимодействия). Чтобы сделать первое, класс должен быть помечен атрибутом [Serializable] . Для последнего он должен быть унаследован от MarshalByRefObject . Если класс ни один, при попытке передать объект в другой домен будет выдано исключение. Однако имейте в виду, что передача по ссылке в значительной степени убивает всю идею, потому что ваш метод по-прежнему будет вызываться в том же домене, в котором существует объект, то есть в домене по умолчанию.

Завершая предыдущий абзац, вы остаются два варианта: либо передать метод, определенный в классе, помеченном атрибутом [Serializable] (и имейте в виду, что объект будет скопирован), либо передать статический метод. Я подозреваю, что для ваших целей вам понадобится первое.

И на всякий случай, если это ускользнуло от вашего внимания, я хотел бы указать, что ваша вторая перегрузка RunInAppDomain (та, которая принимает Действие ) передает метод, определенный для класса, не отмеченного [Serializable] . Не видите там никакого класса? Вам не обязательно: с анонимными делегатами, содержащими связанные переменные, компилятор создаст их для вас. И так уж случилось, что компилятор не удосужился пометить этот автоматически сгенерированный класс [Serializable] . К сожалению, это жизнь: -)

Сказав все это (много слов, не так ли? :-), и приняв клятву не передавать никаких нестатических и не- [Serializable ] , вот ваши новые методы RunInAppDomain :

    /// <summary>
    /// Executes a method in a separate AppDomain.  This should serve as a simple replacement
    /// of running code in a separate process via a console app.
    /// </summary>
    public static T RunInAppDomain<T>(Func<T> func)
    {
        AppDomain domain = AppDomain.CreateDomain("Delegate Executor " + func.GetHashCode(), null,
            new AppDomainSetup { ApplicationBase = Environment.CurrentDirectory });

        try
        {
            domain.SetData("toInvoke", func);
            domain.DoCallBack(() => 
            { 
                var f = AppDomain.CurrentDomain.GetData("toInvoke") as Func<T>;
                AppDomain.CurrentDomain.SetData("result", f());
            });

            return (T)domain.GetData("result");
        }
        finally
        {
            AppDomain.Unload(domain);
        }
    }

    [Serializable]
    private class ActionDelegateWrapper
    {
        public Action Func;
        public int Invoke()
        {
            Func();
            return 0;
        }
    }

    public static void RunInAppDomain(Action func)
    {
        RunInAppDomain<int>( new ActionDelegateWrapper { Func = func }.Invoke );
    }

Если вы все еще со мной, я ценю: -)

Теперь, потратив столько времени на исправление этого механизма, Я собираюсь сказать вам, что в любом случае это было бессмысленно.

Дело в том, что AppDomains не поможет вам в ваших целях. Они заботятся только об управляемых объектах, в то время как неуправляемый код может просочиться и привести к сбою всего, что захочет. Неуправляемый код даже не знает, что есть такие вещи, как домены приложений. Он знает только о процессах.

Итак, в конце концов, лучшим вариантом остается текущее решение: просто создайте другой процесс и будьте довольны этим. И, я согласен с предыдущими ответами, вам не нужно писать другое консольное приложение для каждого случая. Просто передайте полное имя статического метода, и пусть консольное приложение загрузит вашу сборку, загрузит ваш тип и вызовет метод. На самом деле вы можете упаковать его довольно аккуратно, почти так же, как вы пытались с AppDomains. Вы можете создать метод, называемый чем-то вроде «RunInAnotherProcess», который проверит аргумент, получит из него полное имя типа и имя метода (при этом убедитесь, что метод статический) и создаст консольное приложение, которое сделает все остальное.

Я даже не знаю, что есть такие вещи, как домены приложений. Он знает только о процессах.

Итак, в конце концов, лучшим вариантом остается текущее решение: просто создайте другой процесс и будьте довольны этим. И, я согласен с предыдущими ответами, вам не нужно писать другое консольное приложение для каждого случая. Просто передайте полное имя статического метода, и пусть консольное приложение загрузит вашу сборку, загрузит ваш тип и вызовет метод. На самом деле вы можете упаковать его довольно аккуратно, почти так же, как вы пытались с AppDomains. Вы можете создать метод, называемый чем-то вроде «RunInAnotherProcess», который проверит аргумент, получит из него полное имя типа и имя метода (при этом убедитесь, что метод статический) и создаст консольное приложение, которое сделает все остальное.

Я даже не знаю, что есть такие вещи, как домены приложений. Он знает только о процессах.

Итак, в конце концов, лучшим вариантом остается текущее решение: просто создайте другой процесс и будьте довольны этим. И, я согласен с предыдущими ответами, вам не нужно писать другое консольное приложение для каждого случая. Просто передайте полное имя статического метода, и пусть консольное приложение загрузит вашу сборку, загрузит ваш тип и вызовет метод. На самом деле вы можете упаковать его довольно аккуратно, почти так же, как вы пытались с AppDomains. Вы можете создать метод, называемый чем-то вроде «RunInAnotherProcess», который проверит аргумент, получит из него полное имя типа и имя метода (при этом убедитесь, что метод статический) и создаст консольное приложение, которое сделает все остальное.

Он знает только о процессах.

Итак, в конце концов, лучшим вариантом остается текущее решение: просто создайте другой процесс и будьте довольны этим. И, я согласен с предыдущими ответами, вам не нужно писать другое консольное приложение для каждого случая. Просто передайте полное имя статического метода, и пусть консольное приложение загрузит вашу сборку, загрузит ваш тип и вызовет метод. На самом деле вы можете упаковать его довольно аккуратно, почти так же, как вы пытались с AppDomains. Вы можете создать метод, называемый чем-то вроде «RunInAnotherProcess», который проверит аргумент, получит из него полное имя типа и имя метода (при этом убедитесь, что метод статический) и создаст консольное приложение, которое сделает все остальное.

Он знает только о процессах.

Итак, в конце концов, лучшим вариантом остается текущее решение: просто создайте другой процесс и будьте довольны этим. И, я согласен с предыдущими ответами, вам не нужно писать другое консольное приложение для каждого случая. Просто передайте полное имя статического метода, и пусть консольное приложение загрузит вашу сборку, загрузит ваш тип и вызовет метод. На самом деле вы можете упаковать его довольно аккуратно, почти так же, как вы пытались с AppDomains. Вы можете создать метод, называемый чем-то вроде «RunInAnotherProcess», который проверит аргумент, получит из него полное имя типа и имя метода (при этом убедитесь, что метод статический) и создаст консольное приложение, которое сделает все остальное.

просто создайте другой процесс и будьте счастливы от этого. И, я согласен с предыдущими ответами, вам не нужно писать другое консольное приложение для каждого случая. Просто передайте полное имя статического метода, и пусть консольное приложение загрузит вашу сборку, загрузит ваш тип и вызовет метод. На самом деле вы можете упаковать его довольно аккуратно, почти так же, как вы пытались с AppDomains. Вы можете создать метод, называемый чем-то вроде «RunInAnotherProcess», который проверит аргумент, получит из него полное имя типа и имя метода (при этом убедитесь, что метод статический) и создаст консольное приложение, которое сделает все остальное.

просто создайте другой процесс и будьте счастливы от этого. И, я согласен с предыдущими ответами, вам не нужно писать другое консольное приложение для каждого случая. Просто передайте полное имя статического метода, и пусть консольное приложение загрузит вашу сборку, загрузит ваш тип и вызовет метод. На самом деле вы можете упаковать его довольно аккуратно, почти так же, как вы пытались с AppDomains. Вы можете создать метод, называемый чем-то вроде «RunInAnotherProcess», который проверит аргумент, получит из него полное имя типа и имя метода (при этом убедитесь, что метод статический) и создаст консольное приложение, которое сделает все остальное.

и пусть консольное приложение загрузит вашу сборку, загрузит ваш тип и вызовет метод. На самом деле вы можете упаковать его довольно аккуратно, почти так же, как вы пытались с AppDomains. Вы можете создать метод, называемый чем-то вроде «RunInAnotherProcess», который проверит аргумент, получит из него полное имя типа и имя метода (при этом убедитесь, что метод статический) и создаст консольное приложение, которое сделает все остальное.

и пусть консольное приложение загрузит вашу сборку, загрузит ваш тип и вызовет метод. На самом деле вы можете упаковать его довольно аккуратно, почти так же, как вы пытались с AppDomains. Вы можете создать метод, называемый чем-то вроде «RunInAnotherProcess», который проверит аргумент, получит из него полное имя типа и имя метода (при этом убедитесь, что метод статический) и создаст консольное приложение, которое сделает все остальное.

75
ответ дан 7 November 2019 в 11:45
поделиться

You don't have to create many console applications, you can create a single application that will receive as parameter the full qualified type name. The application will load that type and execute it.
Separating everything into tiny processes is the best method to really dispose all the resources. An application domain cannot do full resources disposing, but a process can.

7
ответ дан 7 November 2019 в 11:45
поделиться

Рассматривали ли вы открытие канала между основным приложением и вспомогательными приложениями? Таким образом, вы можете передавать более структурированную информацию между двумя приложениями без анализа стандартного вывода.

2
ответ дан 7 November 2019 в 11:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: