2010-08-04 9 views
5

Jestem nowy w C++/CLI, więc proszę o mnie ...Jak wyczyścić pliki .NET, gdy biblioteka DLL C++/CLI zostanie zwolniona?

Pracuję nad mieszaną biblioteką DLL C++/CLI, która powinna działać jako pomost między procesem Win32 a zestawem .NET . W DLL, potrzebuję pewnych rzeczy .NET, aby były obecne w czasie życia biblioteki DLL. Inicjowanie nie jest tak dużym problemem, ale nie mogłem się domyślić, kiedy mogę bezpiecznie wyczyścić pliki .NET. Typowe funkcje C++ (DLL_PROCESS_DETACH, zmienne globalne i statyczne locals d'tors) wydają się być wywoływane po zniknięciu CLR.

Więc, co jest sposobem, aby otrzymywać powiadomienia DLL ma się odczepić od CLR, więc mogę zwolnić odniesienia .NET trzymam?

Odpowiedz

2

Dobrze, odpowiadając na moje własne pytanie wydaje się niezgrabny, ale ten nie został zaproponowany przez kogoś innego, a to jest to, czego szukałem ... tak:

okazuje Microsoft oferuje egzotyczną odmianę onexit, o nazwie _onexit_m, który powinien być używany w bibliotekach DLL w trybie mieszanym. Podczas korzystania z funkcji _onexit_m w celu zarejestrowania (zarządzanej) funkcji oddzwaniania, funkcja ta zostanie wywołana, gdy biblioteka DLL ma zostać rozładowana, ale zanim CLR zostanie zamknięty. Jest podobny do AppDomain.DomainUnload, suggested by Ben Voigt, ale z jakiegoś powodu nie mogłem uruchomić usługi DomainUnload, a _onexit_m jest prostsze w użyciu IMHO.

0

To może nie mieć zastosowania do strony C++ .NET, ale o ile mi wiadomo, że jedynym sposobem, aby uzyskać CLR, aby zwolnić zespół jest załadowany do dysponowania AppDomain; i jeśli nie masz inżynierii w ręcznym zarządzaniu AppDomain, prawdopodobnie masz tylko początkową AppDomain - czyniąc utylizację równoważnym zabiciem twojej aplikacji.

+0

Nie próbuję zwolnić zespół - ja tylko próbuje uwolnić referencje do obiektów .NET mojego autorstwa i zostały gospodarstwa podczas żywotność DLL ... – eran

+0

Czy obiekty. NET jednorazowego użytku? W takim przypadku możesz spróbować dispose() na tych obiektach po zakończeniu użytkowania. – Kangkan

+0

@Kangkan - mówienie, kiedy użycie jest zakończone jest dokładnie moim problemem ... Łatwo jest wiedzieć, kiedy rodzimy świat ma się wkrótce skończyć (proces odłączania, globalizacje itp.), Ale w tym momencie zarządzany świat już zakończyło się. – eran

0

. Dll .NET należy traktować jako zestaw oddzielnych klas ref. Każde wystąpienie klasy ref ma swój własny okres istnienia, a zarządzanie zasobami odbywa się relatywnie do czasu istnienia instancji klasy. Odpowiednio wdrożone Uporządkuj wzór rozwiązuje wszystkie problemy z zarządzaniem zasobami.

Każda klasa C++/CLI, który ma kilka rodzimych zasobów, lub członków klasy jednorazowych, powinna mieć destruktora i opcjonalny finalizatora. W szczególności odwołania do .NET są publikowane w destruktorze klas, który jest odwzorowany na metodę C# Dispose.

+0

Mój problem polega prawdopodobnie na niewłaściwym wzorze, ale nie mogę znaleźć właściwego. Pomyśl o mojej sprawie jako native singleton, który przechowuje odniesienie do obiektu .NET w auto_gcroot. Kiedy singleton jest niszczony, auto_gcroot próbuje zwolnić referencję - ale jest za późno i powoduje awarię. – eran

+1

Jeśli obiekt ma być przechowywany tak długo, jak długo ładowana jest biblioteka DLL, po prostu "wyciekaj" uchwyt. Śmieciarz zadba o to w wyjątkowo mało prawdopodobnym przypadku, gdy CLR nadal działa po zwolnieniu biblioteki DLL. –

+0

Przypuszczam, że zachowujesz referencję auto_gcroot dla jakiejś komunikacji zwrotnej z natywnego singletonu do obiektów .NET. Może lepiej pomyśleć o innym algorytmie oddzwaniania, na przykład na podstawie natywnych zdarzeń? –

2

Jeśli trzeba dbać o AppDomain rozładowuje, użyć zdarzenia AppDomain.DomainUnload robić swoje porządki.

Zgodnie ze słowami STW, biblioteki z zarządzanym kodem nie mogą zostać odłączone od elementu AppDomain, jedynym sposobem odłączenia go od procesu jest zwolnienie elementu AppDomain.

Jeśli nie radzą AppDomains, tylko wyciek zarządzanego zasobu (i odpowiednio przepłukać zasobów niezarządzanych podczas procesu detach). Co więcej, zaprojektuj go jako oprogramowanie awaryjne, aby nie było potrzeby czyszczenia.

+0

DomainUnload wydaje się być prawidłową ścieżką i dopiero zacząłem ją badać, ale nie udało mi się jeszcze jej uruchomić. Co do wycieku zarządzanych zasobów, byłoby ok, ale jest to tak trudne, jak pierwotny problem ... Aby zapobiec ich gc'ed, muszę mieć odniesienia do tych obiektów. Chciałbym móc zwolnić te referencje po rozładowaniu, ale to musi być zrobione, gdy .NET jest nadal w pobliżu. Ustalenie właściwego czasu jest dokładnie moim problemem ... – eran

+0

Możesz uniemożliwić zbieranie przedmiotów przez wywołanie 'GCHandle.Alloc'. Zasoby będą trwać do momentu połączenia z "GCHandle.Free" lub usunięcie appdomain. –