Chyba: AppDomainUnloaded výjimku při použití spravovaných rozšíření součásti Visual C++

Překlady článku Překlady článku
ID článku: 309694 - Produkty, které se vztahují k tomuto článku.
Rozbalit všechny záložky | Minimalizovat všechny záložky

Na této stránce

Příznaky

K tomuto problému dochází při volání z nespravovaný kód na spravovaný kód, včetně přímé volání Nespravovaná k spravovány v rámci jednoho DLL. Například problému může dojít při MEC + +/ IJW používán ASP.NET aplikací. V ASP.NET mohou způsobit různé události aplikací znovu do nové AppDomain. Pokud používáte součásti MEC ++ a IJW v této aplikaci, můžete obdržet chybovou zprávu AppDomainUnloadException.

Příčina

Jako část implementace IJW při načtení spravované DLL, která jste vytvořili pomocí kompilátoru C++ modulu runtime vytvoří thunks přechody z nespravovaný kód spravovaný kód. Tyto thunks obsahovat odkaz AppDomain, ve kterém DLL načte. Modulu runtime není znovu tyto thunks, pokud znovu načte DLL; také, modulu runtime neaktualizuje odkaz, když původní AppDomain uvolní a načte DLL v jiném AppDomain.

Když program provádí přechod z nespravovaný kód k spravovaný kód, program používá zastaralé AppDomain odkazovat spustit spravovaný kód. I když je stále načten původní AppDomain, kód nemůže získat přístup k statické pole, protože pole jsou určité domény AppDomain.

Jak potíže obejít

Následující zástupná řešení jsou seskupeny podle dva scénáře:
  • Přechod z nespravovaný kód spravovaný kód přes dvě knihovny
  • Přechod z nespravovaný kód spravovaný kód ve stejné knihovně DLL

Spravované nespravovaný kód na kód přechod přes dva dll

Tento konkrétní problém, použijte některou z následujících metod.

Řešení 1

Klienti ASP.NET povolit hostitelský proces ASP.NET k vypnutí podle soutisku událostí DomainUnload. Musíte však nejprve zaregistrovat delegát událost DomainUnload. Postupujte takto:
  1. V Application_Start metoda třídy aplikace ASP.NET registrovat delegáta s názvem domény AppDomain uvolní.
  2. Delegát registrované ukončit činnost aspnet_wp.exe procesu.
Poznámka: Toto řešení všechny aplikace ASP.NET způsobuje restartování počítače na; data stavu relace v procesu pro všechny tyto aplikace budou ztracena. V Internetu informační služba (IIS) 6.0 v počítači se systémem Windows 2003 Server, můžete nakonfigurovat program pro jednu aplikaci za režimu procesu. Další informace o configuing fondů aplikací naleznete na následujícím webu:
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);
}
				

Řešení 2

Nahraďte všechny přechody ze nespravovaný kód spravovaný kód volání prostřednictvím ukazatel Nespravovaná funkce, vytvořit pomocí delegát (což je konkrétní AppDomain). Delegát je zařadit do nespravovaný kód pomocí služby vyvolání Platform (P/Invoke) namísto IJW.

Nespravovaná DLL popsané v části "Další informace" tohoto článku pro následující ukázkový kód demonstruje použití P/Invoke použití zpětného volání metody:
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;
		}
	};
}
				

Spravované nespravovaný kód na kód přechod v stejné DLL

V tomto scénáři, můžete mít Nespravovaná metody (označených s # pragma Nespravovaná) volání metod na spravované součásti ve stejné knihovně DLL, jak je uvedeno v části "Další informace" tohoto článku. Tento konkrétní problém, použijte některou z následujících metod:

Řešení 1

Zařazování ukazatel funkce jako delegát a pomocí tohoto delegáta. Protože P/Invoke nelze použít na stejném DLL, vytvořit souhrnný DLL, která pomáhá zařazení delegáta ukazatel funkce. Exportovaná funkce vrátí adresu delegát je předán. Následující ukázkový kód je příkladem tohoto zástupného řešení:
//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;
}
				
je následující ukázkový kód pro rozšíření Managed C++ pro sestavení používá předchozí 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();
     }
}
				

Řešení 2

Rozdělit vaše MEC ++ sestavení do dvě knihovny, jednu, která obsahuje pouze spravované součásti a jiné, které obsahuje pouze Nespravovaná součásti a potom pomocí P/Invoke popsané řešení 2 Scénář 1.

Prohlášení

Společnost Microsoft potvrzuje, že se jedná o chybu v Microsoft produktů uvedených na začátku tohoto článku.

Další informace

Problém je více převážnou, pokud aplikace klienta nebo hostitele musí uvolnit a znovu načtěte AppDomains a aplikace obsahuje přechody ze nespravovaný kód k spravovaný kód, které používají součásti MEC ++ a IJW. ASP.NET je dobrým příkladem takové hostitele. V ASP.NET mohou být události může aktivační událost události unload AppDomain nic z dotýkání určité soubory (například Machine.config) křížení prahová hodnota využití paměti.

Kroky pro reprodukci chování

V tomto příkladu máte aplikace ASP.NET, která volá komponenty MEC ++ a tato součást má ukazatel na funkci, která odkazuje na jednu z metod v součásti MEC ++. Součást předá ukazatel funkce jednu z následujících:
  • Funkce, který byl exportován Nespravovaná DLL
  • Nespravovaná metodu ve stejné knihovně DLL
Nespravovaný kód vytváří zpětné volání pomocí ukazatel funkce byla přijata z komponenty MEC ++.

V následujících scénářích je možné, že před Nespravovaná funkce vyvolá ukazatel funkce, původní AppDomain, ve kterém byl načten DLL je uvolněn. Za takových podmínek nespravovaný kód stále odkazuje na původní AppDomain a pokouší se volání spravovaný kód v tomto kontextu.
  • Spravované nespravovaný kód na kód přechod mezi dvěma dll

    Volání exportovaná Nespravovaná funkce DLL z MEC ++ sestavení jedním z následujících způsobů:
    • pomocí IJW
    • pomocí P/Invoke
    Následující ukázkový kód používá Nespravovaná DLL (Win32.dll), která metoda exportuje.
    //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;
    }
    					
    spravovaných sestavení C++ mohou volat tuto metodu prostřednictvím IJW propojením Win32.lib a včetně soubor příslušné záhlaví. Následující ukázkový kód ukazuje, jak použít exportovaný metodu. # 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;
    		}
    	};
    }
    					
  • Spravované nespravovaný kód na kód přechod v stejné DLL

    V tomto scénáři sestavení MEC ++ obsahuje Nespravovaná metody (označených s # pragma Nespravovaná), volání metod součást MEC ++ ve stejné knihovně DLL znázorněno v následující ukázkový kód.
    #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();
         }
    }
    					

Odkazy

Další informace navštivte následující webové servery Microsoft Developer Network (MSDN):
Domény aplikace
http://msdn2.microsoft.com/en-us/library/cxk374d9(vs.71).aspx?frame=true

Třídy AppDomain
http://msdn2.microsoft.com/en-us/library/system.appdomain(vs.71).aspx

Třída AppDomainUnloadedException
http://msdn.microsoft.com/en-us/library/system.appdomainunloadedexception(VS.71).aspx

Řízená rozšíření pro programování C++
http://msdn2.microsoft.com/en-us/library/aa712574(vs.71).aspx

Vytváření aplikací ASP.NET Web
http://msdn.microsoft.com/en-us/library/aa719794.aspx

Režim izolace pracovního procesu
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/34604f82-9175-4d48-b5ea-1e11f19db5f3.mspx?mfr=true

Vlastnosti

ID článku: 309694 - Poslední aktualizace: 17. května 2007 - Revize: 4.7
Informace v tomto článku jsou určeny pro produkt:
  • Microsoft Visual C++ .NET 2002 Standard Edition
  • Microsoft .NET Framework 1.0
Klíčová slova: 
kbmt kbbug kbijw kbmanaged kbpending KB309694 KbMtcs
Strojově přeložený článek
Důležité: Tento článek byl přeložen pomocí software společnosti Microsoft na strojový překlad, ne profesionálním překladatelem. Společnost Microsoft nabízí jak články přeložené překladatelem, tak články přeložené pomocí software na strojový překlad, takže všechny články ve Znalostní databázi (Knowledge Base) jsou dostupné v češtině. Překlad pomocí software na strojový překlad ale není bohužel vždy dokonalý. Obsahuje chyby ve skloňování slov, skladbě vět, nebo gramatice, podobně jako když cizinci dělají chyby při mluvení v češtině. Společnost Microsoft není právně zodpovědná za nepřesnosti, chyby nebo škody vzniklé chybami v překladu, nebo při použití nepřesně přeložených instrukcí v článku zákazníkem. Společnost Microsoft aktualizuje software na strojový překlad, aby byl počet chyb omezen na minimum.
Projděte si také anglickou verzi článku:309694

Dejte nám zpětnou vazbu

 

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