Appdomain issue

В останні дні я вдарив головою навпроти стіни, намагаючись з'ясувати проблему, пов'язану з доменом. Я створив невелику службу Windows, яка запускає плагіни. Те, як це працює, кожен плагін - це DLL, який завантажується у власний окремий домен домену, використовуючи "CreateInstanceAndUnwrap", і я зберігаю посилання на appdomain, і після того, як плагін завершиться, я закрив прикладне ім'я, створене для цього плагіна.i 'm використовуючи тіньову копію, щоб дозволити оновлення плагінів під час їх роботи в рамках.Ок добре до цих пір. Він протримався протягом 6 місяців ідеально, аж до останнього тижня, коли я вирішив поставити основну функціональність системи в окрему DLL також і виконати це dll в окремому домені домену.Таким чином, як це працює зараз, це:

Служба Windows з'являється. Основне dll завантажується та виконується за допомогою CreateInstanceAndUnwrap, який, у свою чергу, несе відповідальність за запуск додатків у власному окремому домені додатків. (використовуючи CreateInstanceand ..)

У мене є кілька різних місць для зборів: Bin Folder (Бен у службі Windows тримає лише DLL, що використовуються сервісом) Папка Core DLLs (Core DLLs з'являються тут) Список літератури (будь-які посилання наведені тут) Папка "Плагіни" (плагіни з'являються тут)

Я вирішую будь-який необгрунтований DLL, підключивши до кожного доповнювача оброблювача через appdomain. Це означає, що DLL може завантажуватися з мережі.

Тепер проблема полягає в тому, що служба Windows запустила на один день, а пам'ять пішла на висоту до 1.5G. Я створив звалище пам'яті і, схоже, що завантажені модулі мають всього 100 МБ всього 1.5 ГБ, тому я не знаю, куди збиратиметься вся ця пам'ять. Використовуючи debugdiag, я побачив попередження про фрагментацію купи, але я не знаю, де я повинен почати діагностувати проблему. Зазвичай, коли система запускається протягом дня, вона споживає щось на зразок 100M. Також це не стосується плагінів, як коли я відмовився від моїх змін у рамках, використання пам'яті стало нормальним, як і раніше. Коли я створюю додаткові домени для плагінів, я перемикаю BasePath і шлях контейнера домену appdomain у папки CORE та Reference, які мають більшість DLL там, сподіваючись, що рішення про збірку буде викликано рідше.

Я подивився на журнали Fusion, а також читав трохи більше про завантаження контекстів, таких як за замовчуванням, від і ніхто, але я не впевнений, що це правильний шлях, щоб взяти.

Будь-які ідеї?

2
Я використовую інтерфейс, щоб отримати проксі другого домену домену, і нещодавно виникла помилка про те, що відтворення виникла через знаменитого "невідповідного виключення з виду типу", таким чином, я перемкнув зворотний виклик на динамічний тип замість: D я знаю це не є гарним рішенням проблеми, але він вирішив проблему випуску. Я думаю, що декілька версій інтерфейсу DLL завантажується до викликаючого доменного домену, і саме тому він дає виключення типу cast.i створіть головний домен і також плагін appdomains за допомогою createinstanceandunwrap.for вирішити asselmbly події я використовую "LoadFrom"
додано Автор James, джерело

1 Відповіді

Я думаю це:

, коли я вирішив поставити основну функціональність системи в a   Відокремити DLL також і виконати це DLL в окремій доменній області. Таким чином   як працює зараз:

     

Служба Windows з'являється. Основна dll завантажується та виконується за допомогою   CreateInstanceAndUnwrap, який, у свою чергу, несе відповідальність за запуск   плагіни у власних окремих доменах додатків (за допомогою CreateInstanceand ..)

Може бути, це може бути недоліком:

From http://msdn.microsoft.com/en-us/library/3c4f1xde.aspx

Якщо ви зробили перший виклик методу M об'єкта типу T1   що було повернуто CreateInstanceAndUnwrap, і цей метод робить   ранній зв'язаний виклик методу об'єкта типу T2 в збірці С   крім поточної збірки або агрегату, що містить T1,   збірка C завантажується в поточний домен програми. Це завантаження   відбувається, навіть якщо раніше зв'язаний виклик T1.M() був зроблений в тілі   DynamicMethod, або в іншому динамічно створеному коді. Якщо   поточний домен є доменом за замовчуванням, збірка C не може бути розвантажена   поки процес не закінчиться.

У такому випадку ви можете використовувати Reflection для виконання "відповідного" дзвінка, щоб усунути ранній зв'язок.

1
додано
Віддзеркалення можна використовувати для виклику коду, який не генерується динамічно. Наприклад, використовуючи Reflecttion MethodInfo, не генерується жодний динамічний код, і його можна використовувати для виклику методів, визначених у час компіляції. Тому я думаю, що це ще одна можливість зламати раннє зв'язування.
додано Автор Nathan, джерело
Безумовно, головоломка. Ви можете подивитися на stackoverflow.com/questions/2634858/ … з точки зору вирішення проблеми відображення - хоча це трохи інша справа (я не вважаю, що ви використовуєте динамічне ключове слово будь-де ) Але це може дати деякі підказки щодо надання деяких додаткових метаданих для відображення - хоча чесно з цим конкретним аспектом рефлексії, я отримую трохи від мого досвіду.
додано Автор Nathan, джерело
Просто ясно, коли ви кажете, що ви все ще не в змозі вирішити цю проблему, чи ви все ще говорите про те, що не можете отримати відображення, щоб працювати? Чи ви могли отримати відображення на роботі, і це не вирішити проблему пам'яті?
додано Автор Nathan, джерело
Одне інше можливе виправлення приходить на розум - оберніть проксі-дзвінок, який ви викликаєте з віддзеркаленням у класі часу компіляції, а замість цього викликає загорнений (компіляційний час) метод через відображення - так що ви не безпосередньо відбиваєте на об'єкті MarshalByRef .
додано Автор Nathan, джерело
Я буду досліджувати далі, якщо це відбувається, але коли я налагоджував службу Windows, я не бачив жодних дублікатів DLL, які завантажуються, або основний додаток домену завантажується з DLL з плагінів взагалі. це здавалося все гаразд, навіть коли я скинув 1.5G працює служба, debugdiag не проявляти жодних ознак цього. Завантажені модулі = 100M!
додано Автор James, джерело
Також док каже: "Це навантаження відбувається, навіть якщо ранній зв'язаний виклик до T1.M() був зроблений в тілі DynamicMethod або в іншій динамічно створеній треке". Таким чином, це означає, що використання віддзеркалення, ймовірно, також не спрацює (якщо це так)
додано Автор James, джерело
Я спробував це, але GetMethod, схоже, не працює над динамічно генерованим проксі-сервером. Я отримую "метод не існує на системі.marshalByRef" виключення.
додано Автор James, джерело
також, здається, це може стати причиною проблем пам'яті у моєму випадку, я дізнався, що деякі плагіни фактично завантажуються в початковий домен. (але вони не повинні приймати 1.5G так що я все ще не впевнений)
додано Автор James, джерело
Так, я все ще не можу вирішити проблему :( будь-які ідеї?
додано Автор James, джерело
Я не міг отримати відображення на роботу, але я спробую інший підхід, про який ви щойно згадували.
додано Автор James, джерело
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug