Совсем не факт, что выгрузка текущего по памяти COM-компонента (который про домены приложений и .Net вообще ничего не знает) приведет к тому, что утекшая память будет освобождена.
Я бы сделал отдельный ПРОЦЕСС, использующий этот компонент. Запускал бы его для импорта 1000 объектов, убивал, и запускал снова. Взаимодействовать с процессом можно через объекты Windows (события и т.п.)
Re[3]: Асинхронное выполнение длительной операции в другом AppDomain
Здравствуйте, Shefango, Вы писали:
S>STA модель нужна для того, что нужный COM-компонент работает исключительно в ней. S>Проблема вот в чем. Этот компонент сам по себе течет по памяти. Если им прокачать большой объем данных, то он валится с OutOfMemory. Следовательно, компонент нужно как-то выгружать. Насколько я знаю, выгрузить отдельную сборку из запущенного приложения нельзя, но можно выгрузить домен приложения, в который она загружена.
Если ваш компонент течет unmanaged памятью то (компонент у вас на чем написан?), выгрузка домена его никак от этого не спасет — тут надо выносить в отдельный процесс.
Если вы корректно освобождете все ссылка на объект (Marshal.ReleaseComObject) то, особой нужды в AppDomain нет. Если нет, то стоит задуматься на тему как finalizer thread будет взаимодействовать с возданным вами sta апартментом (и когда это может произойти)
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Асинхронное выполнение длительной операции в другом AppDomain
Доброго времени суток.
Столкнулся с такой проблемой. Мне нужно провести обмен данными с одной системой, предоставляющей только COM-интерфейс. Делаю я это так:
При первом нажатии на кнопку startButton код отрабатывает нормально. При повторном нажатии обмен тоже отрабатывает, но при закрытии приложения вываливается AppCrash c исключением 0x0eedfade.
Если этот код вызывать синхронно, так:
то импорт, выполняемый многократно без перезапуска приложения отрабатывает нормально и приложение не крэшится при выходе.
Помогите решить проблему с выполнением кода в отдельном потоке.
А попробуйте делегировать создание потока самому домену,
т.е. есть некий worker, вы вызываете у него метод, и в этом методе
создаете поток. Потом выгружаете домен. Если не ошибаюсь, можно
синхронизироваться через какой-нибудь соотв. статический примитив.
Кодом людям нужно помогать!
Re[2]: Асинхронное выполнение длительной операции в другом AppDomain
Здравствуйте, Sharov, Вы писали:
S>А попробуйте делегировать создание потока самому домену, S>т.е. есть некий worker, вы вызываете у него метод, и в этом методе S>создаете поток. Потом выгружаете домен. Если не ошибаюсь, можно S>синхронизироваться через какой-нибудь соотв. статический примитив.
Не совсем понял вашу мысль...
Мой небогатый опыт взаимодействия с .NET Application Domains показывает, что если создавать AppDomain в потоке UI WinForms (как во втором листинге с закомментированным Thread t = new Thread...), то код в нем будет исполнятся в том же потоке UI WinForms (и, соответственно, фризить форму). Это решает мою проблему, но хотелось бы показывать пользователю прогресс выполнения и дать возможность отмены.
Или вы предлагаете использовать какой-нибудь механизм асинхронных вызовов из .NET Framework, типа BackgroundWorker или AsyncOperation? Эти варианты мне не подходят, так как мне нужно работать с потоком, у которого ApartmentState = STA. А у потоков из пула .NET ApartmentState = MTA.
Не могли бы вы пояснить ваше предложение подробнее?
Re[3]: Асинхронное выполнение длительной операции в другом AppDomain
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, Shefango, Вы писали:
S>>Не могли бы вы пояснить ваше предложение подробнее?
S>Попробуйте перенести логику создания потока в методы AbstractImport'а.
Здравствуйте, Shefango, Вы писали:
S>Доброго времени суток. S>Столкнулся с такой проблемой. Мне нужно провести обмен данными с одной системой, предоставляющей только COM-интерфейс. Делаю я это так:
1. Посмотрите в журнале windows — там вполне может быть информация о возникшем исключении.
2. Зачем вам sta модель, рассчитываете на то, что AppDomian.Unload будет крутить цикл выборки сообщений? Или может finalizer святым духом его воскресит и вызовет там Release для "подвисшего" COM объекта?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[2]: Асинхронное выполнение длительной операции в другом AppDomain
Здравствуйте, TK, Вы писали:
TK>Здравствуйте, Shefango, Вы писали:
S>>Доброго времени суток. S>>Столкнулся с такой проблемой. Мне нужно провести обмен данными с одной системой, предоставляющей только COM-интерфейс. Делаю я это так:
TK>1. Посмотрите в журнале windows — там вполне может быть информация о возникшем исключении.
Это было сделано в первую очередь. Приложение падает с кодом исключения 0x0eedfade. Нагуглить по этому коду ничего толкового не удалось. В подавляющем большинстве случаев даются только общие рекомендации: переустановить проблемное приложение, пройтись антивирусом, выполнить проверку файлов Windows (sfc /scannow) и переустановить Windows.
TK>2. Зачем вам sta модель, рассчитываете на то, что AppDomian.Unload будет крутить цикл выборки сообщений? Или может finalizer святым духом его воскресит и вызовет там Release для "подвисшего" COM объекта?
STA модель нужна для того, что нужный COM-компонент работает исключительно в ней.
Проблема вот в чем. Этот компонент сам по себе течет по памяти. Если им прокачать большой объем данных, то он валится с OutOfMemory. Следовательно, компонент нужно как-то выгружать. Насколько я знаю, выгрузить отдельную сборку из запущенного приложения нельзя, но можно выгрузить домен приложения, в который она загружена.
Идея была такая: вынести все связанное с импортом в отдельную сборку, загружать ее в отдельном домене приложений Worker, импортировать 1000 записей, выгружать домен приложений Worker (полагая, что выгрузится и COM-компонент), снова загружать сборку с кодом импорта в домен Worker, импортировать 1000 и так далее.
Ну и плюс к этому хотелось дать пользователю возможность прерывания импорта и просмотра прогресса. Поэтому импорт запускается в отдельном потоке.
Мне непонятно вот что: если импорт запускать один раз, то все работает без ошибок. Если два и более раз подряд — то валится с исключением.
Re[4]: Асинхронное выполнение длительной операции в другом AppDomain
Здравствуйте, aloch, Вы писали:
A>Здравствуйте, Shefango, Вы писали:
A>Совсем не факт, что выгрузка текущего по памяти COM-компонента (который про домены приложений и .Net вообще ничего не знает) приведет к тому, что утекшая память будет освобождена.
В общем, вы правы. Однозначного ответа на вопрос будет ли освобождаться память при выгрузке домена приложения, в который загружена сборка обвязки COM-компонента мне не удалось. Поэтому решил сам попробовать.
A>Я бы сделал отдельный ПРОЦЕСС, использующий этот компонент. Запускал бы его для импорта 1000 объектов, убивал, и запускал снова. Взаимодействовать с процессом можно через объекты Windows (события и т.п.)
Спасибо за совет, я и сам подумывал так сделать если не выгорит вариант с доменом приложения.
Re[4]: Асинхронное выполнение длительной операции в другом AppDomain
Здравствуйте, TK, Вы писали:
TK>Здравствуйте, Shefango, Вы писали:
S>>STA модель нужна для того, что нужный COM-компонент работает исключительно в ней. S>>Проблема вот в чем. Этот компонент сам по себе течет по памяти. Если им прокачать большой объем данных, то он валится с OutOfMemory. Следовательно, компонент нужно как-то выгружать. Насколько я знаю, выгрузить отдельную сборку из запущенного приложения нельзя, но можно выгрузить домен приложения, в который она загружена.
TK>Если ваш компонент течет unmanaged памятью то (компонент у вас на чем написан?), выгрузка домена его никак от этого не спасет — тут надо выносить в отдельный процесс. TK>Если вы корректно освобождете все ссылка на объект (Marshal.ReleaseComObject) то, особой нужды в AppDomain нет. Если нет, то
На чем написан компонет с точностью сказать не могу, но скорее всего на Delphi/C++ Builder.
Ссылки освобождаются корректно, проверено путем логгирования в конструкторах и финализаторах классов-обвязок над интерфейсами предоставленными компонентом. Сколько их создается, столько и освобождается, Marshal.ReleaseComObject везде возвращает 0. Но при этом объем памяти процесса со временем все равно растет. Точнее так: перед запуском импорта память — 30 Мб, во время шага импорта — 180 Мб, после завершения шага — 35. После каждого шага импорта количество занимаемой памяти уввеличивается.
TK>стоит задуматься на тему как finalizer thread будет взаимодействовать с возданным вами sta апартментом (и когда это может произойти)
По идее сборщик мусора должен отработать перед выгрузкой домена. В том, что выгрузка домена повлечет освобождение unmanaged памяти я не уверен.
А с STA сборка мусора в этом случае как-то же проходит:
class Program
{
[STAThread]
static void Main()
{
}
}
Re[5]: Асинхронное выполнение длительной операции в другом AppDomain
Здравствуйте, Shefango, Вы писали:
S>А с STA сборка мусора в этом случае как-то же проходит:
STA это для COM, а не для сборщика мусмора. При этом, если сборщику мусора потребуется освободить COM объект созданный в STA то, по правилам ему надо будет сделать это в STA апартменте (т.е. вызов Release надо отмаршалить в нужный поток).
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[6]: Асинхронное выполнение длительной операции в другом AppDomain