2010-08-04 16 views
5

Sono nuovo di C++/CLI, quindi per favore portami con me ...Come si disinstalla .NET quando una DLL C++/CLI scarica?

Sto lavorando su una DLL mista C++/CLI, che dovrebbe fungere da ponte tra un processo Win32 e un assembly .NET. . Nella DLL, ho bisogno di alcune cose di .NET per essere presente durante la vita della DLL. L'inizializzazione non è un grosso problema, ma non riesco a capire quando posso pulire in modo sicuro il materiale .NET. Le solite strutture C++ (DLL_PROCESS_DETACH, variabili globali e locatori statici d'ufficio) sembrano tutte essere chiamate dopo che CLR è andato via.

Quindi, quale è il modo per ottenere la notifica che la DLL sta per staccare dal CLR, quindi posso rilasciare i riferimenti .NET che tengo?

risposta

2

Beh, rispondendo alla mia domanda sembra imbarazzante, ma questo non è stato suggerito da qualcun altro, ed è quello che cercavo ... quindi:

scopre Microsoft offre una variazione di esotico onexit, chiamato _onexit_m, che dovrebbe essere utilizzato nelle DLL in modalità mista. Quando si utilizza _onexit_m per registrare una funzione di callback (gestita), tale funzione verrà chiamata quando la DLL sta per essere scaricata, ma prima che CLR sia stato arrestato. È simile a AppDomain.DomainUnload, suggested by Ben Voigt, ma per qualche motivo non riesco a far funzionare DomainUnload, e _onexit_m è più semplice da usare IMHO.

0

Questo potrebbe non essere applicabile al lato C++ di .NET, ma a mia conoscenza l'unico modo per ottenere il CLR per rilasciare un assembly caricato è quello di disporre dell'AppDomain; e, a meno che tu non abbia pianificato la gestione manuale di AppDomain, probabilmente hai solo l'AppDomain iniziale, rendendo l'eliminazione l'equivalente di uccidere la tua applicazione.

+0

Non sto provando a rilasciare un assembly - Sto semplicemente provando a rilasciare i riferimenti agli oggetti .NET che ho creato, e ho mantenuto durante la vita della DLL ... – eran

+0

Gli oggetti sono dentro. NET usa e getta? In tal caso, provare a disporre() su tali oggetti una volta terminato l'utilizzo. – Kangkan

+0

@Kangkan - dire quando l'uso è finito è esattamente il mio problema ... È facile sapere quando il mondo nativo sta per finire (processo di distacco, globali, ecc.) Ma a quel punto, il mondo gestito ha già conclusa. – eran

0

.NET Dll deve essere considerato come set di classi di riferimento separate. Ogni istanza di classe ref ha una durata specifica e la gestione delle risorse viene eseguita relativamente alla durata dell'istanza della classe. Il modello Dispose correttamente implementato risolve tutti i problemi di gestione delle risorse.

Ogni classe C++/CLI, che ha alcune risorse native o membri della classe usa e getta, deve avere un distruttore e un finalizzatore opzionale. Nello specifico, i riferimenti .NET vengono rilasciati nel distruttore di classe, che viene associato al metodo C# Dispose.

+0

Il mio problema sta probabilmente utilizzando lo schema sbagliato, ma non riesco a capire quello giusto. Pensa al mio caso come un singleton nativo, che memorizza un riferimento a un oggetto .NET in un auto_gcroot. Quando il singleton viene distrutto, auto_gcroot tenta di rilasciare il riferimento, ma è troppo tardi e provoca un arresto anomalo. – eran

+1

Se si intende conservare l'oggetto per tutto il tempo in cui viene caricata la DLL, basta "perdere" l'handle. Il garbage collector si prenderà cura di esso nell'evento estremamente improbabile che CLR sia ancora in esecuzione dopo che la DLL ha scaricato. –

+0

Immagino che tu mantenga il riferimento auto_gcroot per qualche tipo di comunicazione di callback da un singleton nativo agli oggetti .NET. Forse è meglio pensare ad un altro algoritmo di callback, ad esempio, basato su eventi nativi? –

2

Se è necessario occuparsi di AppDomain scarica, utilizzare l'evento AppDomain.DomainUnload per eseguire la pulizia.

Come dice STW, le librerie con codice gestito non possono mai essere scollegate da un AppDomain, l'unico modo per separarlo dal processo è scaricare AppDomain.

Se non si gestisce AppDomain, è sufficiente perdere la risorsa gestita (e svuotare correttamente le risorse non gestite durante lo scollegamento del processo). Meglio ancora, progettalo come software solo per crash, in modo che non sia necessaria alcuna pulizia.

+0

DomainUnload sembra un percorso valido e ho appena iniziato a esplorarlo, ma non sono ancora riuscito a farlo funzionare. Per quanto riguarda la perdita delle risorse gestite, sarebbe ok, ma è difficile come il problema originale ... per evitare che vengano gc, devo avere riferimenti a quegli oggetti. Mi piacerebbe essere in grado di rilasciare tali riferimenti al momento dello scaricamento, ma questo deve essere fatto mentre .NET è ancora in circolazione. Calcolare il momento giusto è esattamente il mio problema ... – eran

+0

È possibile impedire la raccolta di oggetti semplicemente chiamando 'GCHandle.Alloc'. Le risorse dureranno fino a quando una chiamata corrispondente a 'GCHandle.Free' o all'appadain verrà scaricata. –

Problemi correlati