Несколько доменов приложений и нативный код

Мое приложение C # использует собственный код, который не является потокобезопасным.

Я могу запускать несколько процессов этого собственного кода, используя межпроцессное взаимодействие для достижения параллелизма.

Мой вопрос: могу ли я использовать вместо этого домены приложений, чтобы несколько управляемых потоков, каждый в другом домене приложения, вызывали собственный код и не мешали друг другу?

Основная цель - предотвратить разделение процессов.


person Hadar Grubman    schedule 29.04.2014    source источник


Ответы (2)


Да, это можно сделать, но вам следует серьезно оценить, окупаются ли ваши усилия выгодами.

Windows не будет загружать несколько копий неуправляемой DLL, а неуправляемые библиотеки DLL загружаются для каждого процесса (а не для AppDomain). Что вы можете сделать, так это создать несколько временных копий одной и той же DLL, а затем загрузить их с помощью LoadLibrary().

Каждый из них будет загружен для каждого процесса, но они будут отделены друг от друга (поэтому они будут потокобезопасными). Все это можно связать внутри класса, который обертывает неуправляемые вызовы (LoadLibrary, FreeLibrary, GetProcAddress и сам вызов). Он будет использовать меньше ресурсов и будет работать быстрее, чем несколько процессов, но вам придется отказаться от DllImport использования.

Единственное преимущество, которое я вижу, заключается в том, что это будет масштабироваться намного лучше, чем несколько процессов (потому что он использует меньше ресурсов), конечно, если вы повторно используете экземпляры, хранящие кеш (хранить кеш процесса сложнее, чем кеш объекта).

person Adriano Repetti    schedule 29.04.2014

Нет, домены приложений - это концепция чистого управляемого кода. Изоляция достигается за счет разделения корней управляемых объектов. Один AppDomain не может видеть объекты другого, что делает очень безопасным прерывание кода и выгрузку сборок. Никогда не случайно, он выбрасывает все данные, которые могут содержать состояние.

Неуправляемый код полностью не зависит от кучи сборщика мусора и, следовательно, доменов приложений, он будет выделять в своем разделе данных и собственной собственной куче (HeapAlloc). Такие распределения носят глобальный характер. Это делает процесс границей изоляции, вам понадобится вспомогательный процесс, который загружает DLL и взаимодействует с ней с помощью одного из механизмов взаимодействия процессов .NET (сокет, именованный канал, файл с отображением памяти, удаленное взаимодействие, WCF).

Технически вы можете создавать копии DLL, каждая с другим именем. Но это очень плохо масштабируется, и pinvoke очень неудобен, поскольку вы больше не можете использовать [DllImport]. Вам потребуется объявление делегата для каждой экспортируемой функции, а также LoadLibrary () и GetProcAddress () для инициализации объектов делегата.

person Hans Passant    schedule 29.04.2014
comment
Отличный ответ. Есть ли другой способ запустить тот же собственный код, чтобы статические данные не конфликтовали? (кроме нескольких процессов) - person seldary; 29.04.2014