Fehler: AppDomainUnloaded-Ausnahme bei Verwendung verwaltete Erweiterungen für Visual C++-Komponenten

SPRACHE AUSWÄHLEN SPRACHE AUSWÄHLEN
Artikel-ID: 309694 - Produkte anzeigen, auf die sich dieser Artikel bezieht
Alles erweitern | Alles schließen

Auf dieser Seite

Problembeschreibung

Dieses Problem tritt erfolgt ein Aufruf von nicht verwaltetem Code zu verwaltetem Code, einschließlich direkter unmanaged-to-managed-Aufrufe innerhalb einer einzigen DLL. Beispielsweise das Problem kann auftreten, wenn MEC + / IJW wird in ASP.NET verwendet Anwendungen. In ASP.NET kann verschiedene Ereignisse Anwendungen erneut in einer neuen Anwendungsdomäne geladen werden. Wenn Sie MEC-Komponenten und IJW in dieser Anwendung verwenden, wird möglicherweise eine AppDomainUnloadException -Fehlermeldung angezeigt.

Ursache

Als Teil der Implementierung von IJW Wenn eine verwaltete DLL, die Sie mithilfe des C++-Compilers erstellt geladen wird, erstellt die Laufzeit Thunks für Übergänge von nicht verwaltetem Code zu verwaltetem Code. Diese Thunks enthalten einen Verweis auf die Anwendungsdomäne, in dem die DLL lädt. Die Common Language Runtime diese Thunks nicht wiederhergestellt, wenn die DLL erneut lädt, auch die Common Language Runtime beim nicht aktualisiert des Verweis die ursprüngliche Anwendungsdomäne entladen und Laden der DLL in einer anderen Anwendungsdomäne.

Wenn das Programm führt einen Übergang von nicht verwalteten Code an verwalteten Code, die Anwendung verwendet die veraltete Anwendungsdomäne verweisen, verwalteten Code auszuführen. Selbst wenn die ursprüngliche Anwendungsdomäne noch geladen ist, kann nicht statische Felder auf der Code zugreifen, da die Felder für die Anwendungsdomäne spezifisch sind.

Abhilfe

Die folgenden Problemumgehungen sind nach zwei Szenarien zusammengefasst:
  • Ein Übergang von nicht verwaltetem Code zu verwaltetem Code über zwei DLLs
  • Ein Übergang von nicht verwaltetem Code zu verwaltetem Code in derselben DLL

Nicht verwalteter Code, um verwalteten Code Übergang zwischen zwei DLLs

Verwenden Sie eines der folgenden Methoden, um dieses spezielle Problem zu beheben.

1. Umgehungsmöglichkeit

ASP.NET Clients möglich des ASP.NET-Prozess Host zum Herunterfahren durch das DomainUnload -Ereignis auffangen. Allerdings müssen Sie zuerst einen Delegaten für das DomainUnload -Ereignis registrieren. Gehen Sie hierzu folgendermaßen vor:
  1. Erfassen Sie ein Delegat aufgerufen, wenn die Anwendungsdomäne entladen wird in der Application_Start -Methode der Klasse ASP.NET Anwendung .
  2. In den registrierten Delegaten heruntergefahren der Aspnet_wp.exe-Prozess.
Hinweis: Diese Problemumgehung wird aller ASP.NET-Anwendungen auf den Neustart des Computers; die in-Process-Sitzungszustandsdaten für alle diese Anwendungen gehen verloren. In Internet-Informationsdienste (IIS) 6.0 auf einem Computer mit Windows Server 2003, können Sie das Programm für eine Anwendung pro Prozessmodus konfigurieren. Weitere Informationen zu Configuing Anwendungspools die folgenden Microsoft-Website:
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);
}
				

Problemumgehung 2

Ersetzen Sie alle Übergänge von nicht verwaltetem Code zu verwaltetem Code durch Aufrufe über einen nicht verwalteten Funktionszeiger, den Sie mithilfe ein Delegaten (die Anwendungsdomäne spezifische) erstellen. Der Delegat wird an nicht verwalteten Code gemarshallt, indem Plattformaufrufdienste ( P/Invoke ) anstelle von IJW.

Der folgende Beispielcode demonstriert für die nicht verwaltete DLL, die im Abschnitt "Weitere Informationen" dieses Artikels beschrieben, wie mit P/Invoke die Callback-Methode verwenden:
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;
		}
	};
}
				

Nicht verwalteter Code, um verwalteten Code Übergang in der gleichen DLL

In diesem Szenario Sie können haben unmanaged (markiert mit # pragma unmanaged ) Methoden Aufrufen von Methoden einer verwalteten Komponente in derselben DLL wie in den Abschnitt "Weitere Informationen" dieses Artikels dargestellt. Verwenden Sie eine der folgenden Methoden, um dieses spezielle Problem zu beheben:

1. Umgehungsmöglichkeit

Marshallen Sie Ihrer Funktionszeiger als Stellvertretung, und verwenden Sie diesen Delegaten. Da Sie P/Invoke auf die gleiche DLL verwenden können, erstellen Sie eine Wrapper-DLL, die Ihnen zum Marshallen eines Delegaten einen Funktionszeiger hilft. Diese exportierte Funktion gibt die Adresse des Delegaten, der an es übergeben wird. Der folgende Beispielcode ist ein Beispiel für diese Problemumgehung:
//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;
}
				
der folgende Beispielcode ist für die Managed Extensions for C++ Assembly, die vorherigen Helper.dll verwendet:
#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();
     }
}
				

Problemumgehung 2

Teilen Ihre Assembly MEC ++ in zwei DLLs, enthält nur verwaltete Komponenten und andere, enthält nur nicht verwaltete Komponenten, und verwenden Sie P/Invoke , wie in Abhilfe 2 von Szenario 1 beschrieben.

Status

Microsoft hat bestätigt, dass es sich hierbei um ein Problem bei den in diesem Artikel Microsoft-Produkten handelt.

Weitere Informationen

Das Problem ist weiter verbreitet, wenn die Host oder Clientanwendung entladen und Laden Anwendungsdomänen muss und die Anwendung enthält Übergängen aus nicht verwaltetem Code zu verwaltetem Code, die MEC ++ und IJW-Komponenten verwenden. ASP.NET ist ein gutes Beispiel für solche Host. In ASP.NET können die Ereignisse, die eine Anwendungsdomäne entladen Ereignis auslösen können alles aus über ein Speichergrenzwert für die Verwendung mit Zugriff auf bestimmte Dateien (z. B. Machine.config) sein.

Schritte zum Reproduzieren des Verhaltens

In diesem Beispiel Sie haben eine ASP.NET-Anwendung, die MEC ++-Komponente aufruft, und diese Komponente besitzt einen Funktionszeiger, der auf eine der Methoden in der MEC ++ Komponente verweist. Die Komponente übergibt den Funktionszeiger auf eine der folgenden:
  • eine Funktion, die von einer nicht verwalteten DLL exportiert wurde
  • eine nicht verwaltete Methode in derselben DLL
Der nicht verwaltete Code erleichtert dann einen Rückruf den Funktionszeiger, der aus der MEC ++ Komponente empfangen wurde.

In den folgenden Szenarien ist es möglich, bevor die nicht verwaltete Funktion den Funktionszeiger aufruft, die ursprüngliche Anwendungsdomäne, in dem die DLL geladen wurde, entladen wird. Solche Bedingungen nicht verwaltete Code noch verweist auf die ursprüngliche Anwendungsdomäne und versucht, um verwalteten Code in diesem Kontext aufrufen.
  • nicht verwalteter Code, um verwalteten Code Übergang zwischen zwei DLLs

    Rufen eine exportierte nicht verwaltete DLL-Funktion einer MEC-Assembly in eine der folgenden Möglichkeiten:
    • mithilfe von IJW
    • mithilfe von P/Invoke
    Der folgende Beispielcode verwendet eine nicht verwaltete DLL (Win32.dll), die eine Methode exportiert.
    //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;
    }
    					
    eine verwaltete C++-Assembly kann diese Methode über IJW aufrufen, durch Verknüpfen der Win32.lib und einschließlich der entsprechenden Header-Datei. Der folgende Beispielcode veranschaulicht die exportierte-Methode verwenden.
    #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;
    		}
    	};
    }
    					
  • nicht verwalteter Code, um verwalteten Code Übergang in der gleichen DLL

    In diesem Szenario die MEC-Assembly enthält verwaltete Methoden (markiert mit # pragma unmanaged ), die auf einer MEC ++ Komponente in derselben DLL Methoden aufrufen wie in den folgenden Beispielcode dargestellt.
    #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();
         }
    }
    					

Informationsquellen

Informationen finden Sie auf den folgenden Websites von Microsoft Developer Network (MSDN):
Anwendungsdomänen
http://msdn2.microsoft.com/en-us/library/cxk374d9(vs.71).aspx?frame=true

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

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

Managed Extensions for C++-Programmierung
http://msdn2.microsoft.com/en-us/library/aa712574(vs.71).aspx

Erstellen von ASP.NET-Webanwendungen
http://msdn.microsoft.com/en-us/library/aa719794.aspx

Arbeitsprozess-Isolationsmodus
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/34604f82-9175-4d48-b5ea-1e11f19db5f3.mspx?mfr=true

Eigenschaften

Artikel-ID: 309694 - Geändert am: Donnerstag, 17. Mai 2007 - Version: 4.7
Die Informationen in diesem Artikel beziehen sich auf:
  • Microsoft Visual C++ .NET 2002 Standard Edition
  • Microsoft .NET Framework 1.0
Keywords: 
kbmt kbbug kbijw kbmanaged kbpending KB309694 KbMtde
Maschinell übersetzter Artikel
Wichtig: Dieser Artikel wurde maschinell und nicht von einem Menschen übersetzt. Die Microsoft Knowledge Base ist sehr umfangreich und ihre Inhalte werden ständig ergänzt beziehungsweise überarbeitet. Um Ihnen dennoch alle Inhalte auf Deutsch anbieten zu können, werden viele Artikel nicht von Menschen, sondern von Übersetzungsprogrammen übersetzt, die kontinuierlich optimiert werden. Doch noch sind maschinell übersetzte Texte in der Regel nicht perfekt, insbesondere hinsichtlich Grammatik und des Einsatzes von Fremdwörtern sowie Fachbegriffen. Microsoft übernimmt keine Gewähr für die sprachliche Qualität oder die technische Richtigkeit der Übersetzungen und ist nicht für Probleme haftbar, die direkt oder indirekt durch Übersetzungsfehler oder die Verwendung der übersetzten Inhalte durch Kunden entstehen könnten.
Den englischen Originalartikel können Sie über folgenden Link abrufen: 309694
Microsoft stellt Ihnen die in der Knowledge Base angebotenen Artikel und Informationen als Service-Leistung zur Verfügung. Microsoft übernimmt keinerlei Gewährleistung dafür, dass die angebotenen Artikel und Informationen auch in Ihrer Einsatzumgebung die erwünschten Ergebnisse erzielen. Die Entscheidung darüber, ob und in welcher Form Sie die angebotenen Artikel und Informationen nutzen, liegt daher allein bei Ihnen. Mit Ausnahme der gesetzlichen Haftung für Vorsatz ist jede Haftung von Microsoft im Zusammenhang mit Ihrer Nutzung dieser Artikel oder Informationen ausgeschlossen.

Ihr Feedback an uns

 

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