Обработка AppDomain.DomainUnload и AppDomain.ProcessExit в C ++ / CLI DLL - PullRequest
0 голосов
/ 29 января 2019

У меня есть драйвер ODBC (то есть DLL, представляющая нативный C api), который внутренне реализован с использованием C ++ / CLI (обертывание некоторого кода C #).

Нам необходимо поддерживать использование этого драйвераиз приложения .NET через System.Data.Odbc, поэтому возникают сложности, связанные с доменами приложений

. Сейчас мы регистрируем обработчик событий AppDomain.DomainUnload и AppDomain.ProcessExit для уничтожения некоторых глобальных объектов C ++ / CLI & C #.хранится в библиотеке DLL, но клиент сообщил о проблеме, в результате которой иногда происходит сбой, поскольку финализатор из управляемого приложения пытается вызвать SQLFreeHandle после того, как мы обработали событие AppDomain.ProcessExit, поэтому он пытается использоватьуничтоженный объект.

Итак, так как финализаторы все еще могут запускаться после AppDomain.ProcessExit, есть ли какой-нибудь способ для моей DLL подключить «настоящий» выход CLR, чтобы получить возможность уничтожить эти объекты до того, как CLR фактически закроетсявниз?(Я уверен, что попытка уничтожить / получить к ним доступ позже во время статической неинициализации или тому подобного приведет к сбоям).Я думаю (но на самом деле не видел), что есть аналогичные проблемы в случае приложений с несколькими доменами приложений (мы создаем один набор объектов внутри нашей DLL на каждый домен приложений; это в некотором роде хак, в идеале мы были бы независимы отПриложение-потребитель см. Как мне получить «родную» DLL-библиотеку, которая использует C ++ / CLI для скрытого запуска управляемого кода в частном домене приложений? )

Другой вопрос:Возможно ли запуск AppDomain.ProcessExit более одного раза в контексте одного процесса?то есть, это только происходит, когда процесс завершается, или это могло произойти «просто», потому что CLR выгружается (и, возможно, он будет загружен еще раз?).Я не уверен, как это будет взаимодействовать с C ++ / CLI DLL, так как я предполагаю, что он потерпит крах, если кто-то попытается вызвать его после выгрузки CLR?(или если такая загруженная DLL препятствует выгрузке CLR? т.е. CLR не будет закрываться, по крайней мере, до тех пор, пока сама DLL не будет выгружена? Это было бы неплохо, но кажется маловероятным, поскольку мы получаем это событие во время загрузки,и ничто не заставляет приложение-потребитель фактически выгружать DLL [тем более, что оно фактически было загружено диспетчером драйверов, а не кодом платформы приложения / .net напрямую])

edit: еще один вопрос, есть лиспособ узнать, выгружается ли текущий AppDomain?Т.е. после событий AppDomain.DomainUnload / AppDomain.ProcessExit, когда работают финализаторы.Я предполагаю, что идентификаторы AppDomain ID могут быть повторно использованы, поэтому я не могу просто хранить набор всех идентификаторов, которые я получал, для событий произвольно долго.edit2: На самом деле я только что нашел https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.isfinalizingforunload?view=netframework-4.7.2 для этого.

...