BUG: AppDomainUnloaded eccezione quando si utilizza gestite le estensioni per i componenti di Visual c ++

Il presente articolo è stato tradotto tramite il software di traduzione automatica di Microsoft e non da una persona. Microsoft offre sia articoli tradotti da persone fisiche sia articoli tradotti automaticamente da un software, in modo da rendere disponibili tutti gli articoli presenti nella nostra Knowledge Base nella lingua madre dell’utente. Tuttavia, un articolo tradotto in modo automatico non è sempre perfetto. Potrebbe contenere errori di sintassi, di grammatica o di utilizzo dei vocaboli, più o meno allo stesso modo di come una persona straniera potrebbe commettere degli errori parlando una lingua che non è la sua. Microsoft non è responsabile di alcuna imprecisione, errore o danno cagionato da qualsiasi traduzione non corretta dei contenuti o dell’utilizzo degli stessi fatto dai propri clienti. Microsoft, inoltre, aggiorna frequentemente il software di traduzione automatica.

Clicca qui per visualizzare la versione originale in inglese dell’articolo: 309694
Questo articolo è stato archiviato. L’articolo, quindi, viene offerto “così come è” e non verrà più aggiornato.
Sintomi
Questo problema si verifica quando viene effettuata una chiamata da codice non gestito a codice gestito, tra cui le chiamate dirette da non gestito a gestito all'interno di una singola DLL. Ad esempio, il problema può verificarsi quando MEC + / IJW è utilizzato in ASP.NET le applicazioni. In ASP.NET, è possono causare vari eventi parte di applicazioni essere ricaricato in un nuovo dominio applicazione. Se si utilizza componenti MEC ++ e IJW in questa applicazione, si può visualizzato un messaggio di errore AppDomainUnloadException .
Cause
Come parte dell'implementazione di IJW, quando viene caricata una DLL gestita creato utilizzando il compilatore c ++, il runtime crea thunk per le transizioni da codice non gestito a codice gestito. I thunk contenere un riferimento all'AppDomain in cui si carica la DLL. Inoltre, il runtime non aggiorna il riferimento quando scarica il dominio applicazione originale e la DLL viene caricata in un altro dominio applicazione Common Language runtime non verrà ricreati i thunk se la DLL viene caricato nuovamente.

Quando il programma esegue una transizione da codice non gestito a codice gestito, viene utilizzato l'AppDomain non aggiornato fare riferimento per eseguire il codice gestito dal programma. Anche se il dominio applicazione originale è ancora caricato, il codice può accedere a campi statici poiché i campi sono specifici per il dominio di applicazione.
Workaround
Soluzioni alternative descritte di seguito sono raggruppate in base a due scenari:
  • Una transizione da codice non gestito a codice gestito in due DLL
  • Una transizione da codice non gestito a codice gestito nella stessa DLL

Codice non gestito per gestito codice transizione tra due DLL

Per risolvere questo problema specifico, utilizzare uno dei seguenti metodi.

Soluzione alternativa 1

Per i client ASP.NET, consentono al processo di host ASP.NET a chiudere registrando l'evento DomainUnload . Tuttavia, è dapprima necessario registrare un delegato per l'evento DomainUnload . Per effettuare questa operazione, attenersi alla seguente procedura:
  1. Nel metodo Application_Start della classe applicazione di ASP.NET, registrare un delegato da chiamare quando scarica il dominio di applicazione.
  2. Nel delegato registrato, arrestare il Aspnet_wp.exe processo.
Nota Questa soluzione alternativa tutte le applicazioni ASP.NET sul computer per riavviare e i dati di stato sessione in-process per tutte queste applicazioni vengono persi. In Internet Information Service (IIS) 6.0 in un computer che esegue Windows Server 2003, è possibile configurare il programma di un'applicazione per la modalità di processo. Per ulteriori informazioni sui pool di applicazioni configuing, visitare il sito di Web di Microsoft:
//Register a delegate to be called when the DomainUnload event fires.protected void Application_Start(Object sender, EventArgs e){     AppDomain.CurrentDomain.DomainUnload+= new EventHandler(ADUnloading);}//This method is called when the AppDomain is about to unload.public void ADUnloading(object s, EventArgs e){     System.Environment.Exit(0);}				

Soluzione 2

Sostituire tutte le transizioni da codice non gestito a codice gestito con chiamate tramite un puntatore a funzione non gestita creato utilizzando un delegato (ovvero AppDomain specifico). Il delegato viene eseguito il marshalling al codice non gestito utilizzando Platform Invocation Services ( P/Invoke ) invece IJW.

Riportato di seguito viene per la DLL non gestita, descritta nella sezione "Informazioni" di questo articolo, il codice di esempio riportato di seguito illustrato come utilizzare P/Invoke utilizzare il metodo di callback:
using namespace System::Runtime::InteropServices; // For DllImportAttribute.namespace ManagedLib{        //Managed delegate declaration.	public __delegate int ManagedFuncDelg();	public __gc class Class1	{			public:		[DllImport("Win32.dll", EntryPoint="callback")]//Assumes that you have a DEF file for the exports.		static int Mgdcallback(ManagedFuncDelg*);                //This method is called from the unmanaged DLL.		static int InternalMethod()		{			return 123;		}		static ManagedFuncDelg* pd = new ManagedFuncDelg(0, &ManagedLib::Class1::InternalMethod);                //This method is called by the client application.		int Func()		{			int ret = ManagedLib::Class1::Mgdcallback(ManagedLib::Class1::pd);			return ret;		}	};}				

Codice non gestito a gestito codice transizione nella stessa DLL

In questo scenario, è possibile che è non gestita metodi (contrassegnati con # pragma unmanaged ) chiamare metodi su un componente gestito nella stessa DLL, come illustrato nella sezione "Informazioni" di questo articolo. Per risolvere questo problema specifico, utilizzare uno dei seguenti metodi:

Soluzione alternativa 1

Eseguire il marshalling come un delegato il puntatore a funzione e utilizzare tale delegato. Poiché non è possibile utilizzare la stessa DLL P/Invoke , è possibile creare un wrapper DLL che consente di eseguire il marshalling di un delegato a un puntatore a funzione. Questa funzione esportata restituisce l'indirizzo del delegato che viene passato al metodo. Nell'esempio di codice riportato di seguito è un esempio di questa soluzione alternativa:
//This is the helper DLL that enables you to marshal the delegate.//Helper.cpp.//Helper DLL code.extern "C" __declspec(dllexport) void* __stdcall FuncInUmDll(void* pv){	return pv;}				
è il seguente codice di esempio per le estensioni gestite per c ++ assembly che utilizza il precedente Helper.dll:
#using <mscorlib.dll>using namespace System;using namespace System::Runtime::InteropServices; // for DllImportAttributenamespace ManagedLib{      //Forward declaration.      __delegate int delg();      int nativefunc(int(__stdcall*)());      [System::Runtime::InteropServices::DllImport("helper.dll", EntryPoint="FuncInUmDll")] int FuncInUmDll(delg*);      //Managed component.      public __gc class Class1{	public:            static int InternalMethod()            {                 return 123;            }            //This method is called by the client application.            int Func()            {                 delg* d= new delg(0, &Class1::InternalMethod);                 int ret = nativefunc((int(__stdcall*)())FuncInUmDll(d));                 return ret;            }      };      #pragma unmanaged     //Unmanaged function calling the managed delegate.     int nativefunc(int(__stdcall*pf)())     {            return pf();     }}				

Soluzione 2

Dividere l'assembly in due DLL MEC ++, uno che contiene solo componenti gestiti e altri che contiene solo i componenti non gestiti e quindi utilizzare P/Invoke , come descritto nella soluzione 2 dello scenario 1.
Status
Microsoft ha confermato che questo un bug in Microsoft i prodotti elencati all'inizio di questo articolo.
Informazioni
Il problema è più diffuso, se l'host o l'applicazione client deve scaricare ricaricare AppDomain e l'applicazione contiene transizioni da codice non gestito a codice gestito che utilizzano componenti MEC ++ e IJW. ASP.NET è un esempio efficace di ad un host. In ASP.NET, è possono che gli eventi che possono attivare un evento di scaricamento di AppDomain essere nulla da attraversare una soglia di utilizzo di memoria per modificare alcuni file (ad esempio, Machine.config).

Procedura per riprodurre il problema

In questo esempio, si dispone di un'applicazione ASP.NET che chiama un componente MEC ++, e questo componente dispone di un puntatore a funzione che fa riferimento a uno dei metodi nel componente MEC ++. Il componente passa il puntatore a funzione a uno dei seguenti:
  • una funzione che è stata esportata da una DLL non gestita
  • un metodo non gestito nella stessa DLL
Il codice non gestito effettua quindi una richiamata automatica utilizzando il puntatore a funzione ricevuto dal componente MEC ++.

Nei seguenti scenari, è possibile che, prima che la funzione non gestita richiami il puntatore a funzione, il dominio applicazione originale in cui è stata caricata la DLL viene scaricato. In tali condizioni, il codice non gestito ancora fa riferimento l'AppDomain originale e tenta di chiamare codice gestito in tale contesto.
  • codice non gestito a gestito codice transizione tra due DLL

    Chiamare una funzione DLL non gestita esportata da MEC ++ assembly in uno dei seguenti modi:
    • utilizzando IJW
    • utilizzando P/Invoke
    Nel codice di esempio seguente viene utilizzata una DLL non gestita (Win32.dll) di un metodo di esportazione.
    //Win32.h.#ifdef WIN32_EXPORTS#define WIN32_API __declspec(dllexport)#else#define WIN32_API __declspec(dllimport)#endif//Declaration.typedef int (__stdcall *funcptr)(void);WIN32_API int __stdcall  callback(funcptr ptr);//Win32.cpp Implementation.//This method is called by the Managed C++ component either by using P/Invoke//or by using IJW.WIN32_API int __stdcall callback(funcptr ptr){	int rtn= ptr();	return rtn;}					
    un assembly c ++ gestito chiamare questo metodo tramite IJW collegando il Win32.lib, incluso il file di intestazione appropriata. Nell'esempio di codice riportato di seguito viene illustrato come utilizzare il metodo esportato. # pragma
    #pragma once#include "win32.h"#using <mscorlib.dll>using namespace System;namespace ManagedLib{	public __gc class Class1	{			public:		static int InternalMethod()		{			return 123;		}                //This method is called by the client application.		int Func()		{			int ret = callback((funcptr)Class1::InternalMethod);			return ret;		}	};}					
  • codice non gestito a gestito codice transizione nella stessa DLL

    In questo scenario, l'assembly MEC ++ contiene metodi non gestiti, (contrassegnati con # pragma unmanaged ), che chiamano metodi su un componente MEC ++ nella stessa DLL, come illustrato nell'esempio di codice seguente.
    #using <mscorlib.dll>using namespace System;namespace ManagedLib{      //Forward declararion      int nativefunc(int(__stdcall*)());      //Managed component      public __gc class Class1{	public:            static int InternalMethod()            {                 return 123;            }            //This method is called by the client application.            int Func()            {                 int ret = nativefunc((int(__stdcall*)())Class1::InternalMethod);                 return ret;            }      };      #pragma unmanaged     //Unmanaged function calling the managed delegate.     int nativefunc(int(__stdcall*pf)())     {            return pf();     }}					
AppDomainUnloadedException AppDomainUnload eccezione

Avviso: questo articolo è stato tradotto automaticamente

Proprietà

ID articolo: 309694 - Ultima revisione: 12/07/2015 07:59:15 - Revisione: 4.7

Microsoft Visual C++ .NET 2002 Standard Edition, Microsoft .NET Framework 1.0

  • kbnosurvey kbarchive kbmt kbbug kbijw kbmanaged kbpending KB309694 KbMtit
Feedback