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

Traduzione articoli Traduzione articoli
Identificativo articolo: 309694 - Visualizza i prodotti a cui si riferisce l?articolo.
Espandi tutto | Chiudi tutto

In questa pagina

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:
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/2a231dcb-d786-4b6d-b3ba-bda04061a5e7.mspx?mfr=true
//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 DllImportAttribute

namespace 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();
         }
    }
    					

Riferimenti

Per ulteriori informazioni, visitare il seguente sito Web Microsoft Developer Network (MSDN):
Domini applicazione
http://msdn2.microsoft.com/en-us/library/cxk374d9(vs.71).aspx?frame=true

Classe AppDomain
http://msdn2.microsoft.com/en-us/library/system.appdomain(vs.71).aspx

Classe AppDomainUnloadedException
http://msdn.microsoft.com/en-us/library/system.appdomainunloadedexception(VS.71).aspx

Estensioni gestite per la programmazione c ++
http://msdn2.microsoft.com/en-us/library/aa712574(vs.71).aspx

Creazione di applicazioni Web ASP.NET
http://msdn.microsoft.com/en-us/library/aa719794.aspx

Modalità di isolamento processo di lavoro
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/34604f82-9175-4d48-b5ea-1e11f19db5f3.mspx?mfr=true

Proprietà

Identificativo articolo: 309694 - Ultima modifica: giovedì 17 maggio 2007 - Revisione: 4.7
Le informazioni in questo articolo si applicano a:
  • Microsoft Visual C++ .NET 2002 Standard Edition
  • Microsoft .NET Framework 1.0
Chiavi: 
kbmt kbbug kbijw kbmanaged kbpending KB309694 KbMtit
Traduzione automatica articoli
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
LE INFORMAZIONI CONTENUTE NELLA MICROSOFT KNOWLEDGE BASE SONO FORNITE SENZA GARANZIA DI ALCUN TIPO, IMPLICITA OD ESPLICITA, COMPRESA QUELLA RIGUARDO ALLA COMMERCIALIZZAZIONE E/O COMPATIBILITA' IN IMPIEGHI PARTICOLARI. L'UTENTE SI ASSUME L'INTERA RESPONSABILITA' PER L'UTILIZZO DI QUESTE INFORMAZIONI. IN NESSUN CASO MICROSOFT CORPORATION E I SUOI FORNITORI SI RENDONO RESPONSABILI PER DANNI DIRETTI, INDIRETTI O ACCIDENTALI CHE POSSANO PROVOCARE PERDITA DI DENARO O DI DATI, ANCHE SE MICROSOFT O I SUOI FORNITORI FOSSERO STATI AVVISATI. IL DOCUMENTO PUO' ESSERE COPIATO E DISTRIBUITO ALLE SEGUENTI CONDIZIONI: 1) IL TESTO DEVE ESSERE COPIATO INTEGRALMENTE E TUTTE LE PAGINE DEVONO ESSERE INCLUSE. 2) I PROGRAMMI SE PRESENTI, DEVONO ESSERE COPIATI SENZA MODIFICHE, 3) IL DOCUMENTO DEVE ESSERE DISTRIBUITO INTERAMENTE IN OGNI SUA PARTE. 4) IL DOCUMENTO NON PUO' ESSERE DISTRIBUITO A SCOPO DI LUCRO.

Invia suggerimenti

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com