Error: Las extensiones para componentes de C++ administrado de AppDomainUnloaded excepción cuando se utiliza

Seleccione idioma Seleccione idioma
Id. de artículo: 309694 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Síntomas

Este problema se produce cuando se realiza una llamada desde código no administrado a código administrado, incluidas llamadas directas unmanaged-to-managed dentro de un solo archivo DLL. Por ejemplo, el problema puede producirse cuando MEC + / IJW se utiliza en ASP.NET aplicaciones. En ASP.NET, diversos eventos pueden hacer que las aplicaciones para cargarse en un nuevo AppDomain. Si utiliza componentes MEC ++ y IJW en esta aplicación, puede recibir un mensaje de error AppDomainUnloadException .

Causa

Como parte de la implementación de IJW, cuando carga una DLL administrada que creó utilizando el compilador de C++, el motor en tiempo de ejecución crea los thunks de transiciones desde código no administrado a código administrado. Estos procesadores contener una referencia para el dominio de aplicación en el que se carga la DLL. El motor en tiempo de ejecución no volver a crear estos procesadores si la DLL de carga de nuevo; Además, el motor en tiempo de ejecución no actualiza la referencia cuando descarga el AppDomain original y se carga la DLL en otro dominio de aplicación.

Cuando el programa realiza una transición desde código no administrado a código administrado, el sistema utiliza el AppDomain anticuado referencia para ejecutar el código administrado. Aunque el AppDomain original está todavía cargado, el código no puede tener acceso a los campos estáticos porque los campos son específicos del dominio de aplicación.

Solución

Las siguientes soluciones se agrupan según dos escenarios:
  • Una transición desde código no administrado a código administrado a través de dos archivos DLL
  • Una transición desde código no administrado a código administrado en la misma DLL

Código no administrado a administrado transición de código en dos archivos DLL

Utilice uno de los métodos siguientes para resolver este problema específico.

Solución 1

Para los clientes ASP.NET, permita que la cierre captura el evento DomainUnload el proceso de host ASP.NET. Sin embargo, primero debe registrar a un delegado para el evento DomainUnload . Para ello, siga estos pasos:
  1. En el método Application_Start de la clase de aplicación de ASP.NET, registrar un delegado para llamarlo cuando se descarga el dominio de aplicación.
  2. En el delegado registrado, apague el aspnet_wp.exe proceso.
Nota Esta solución provisional hace que todas las aplicaciones ASP.NET en el reinicio del equipo, se perderán los datos de estado de sesión en proceso de todas estas aplicaciones. En Internet Information Service (IIS) 6.0 en un equipo que ejecuta Windows 2003 Server, puede configurar el programa para una aplicación de modo de proceso por. Para obtener más información acerca de grupos de aplicaciones configuing, visite el siguiente sitio Web de 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);
}
				

Solución 2

Reemplace todas las transiciones de código no administrado a código administrado con llamadas a través de un puntero de función no administrada que se crea mediante un delegado (que es específica de AppDomain). Las referencias del delegado se calculan al código no administrado mediante servicios de invocación de plataforma ( P/Invoke ) en lugar de IJW.

Para la DLL no administrada descrita en la sección "Más información" de este artículo, el código de ejemplo siguiente muestra cómo utilizar P/Invoke para utilizar el método de devolución de llamada:
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;
		}
	};
}
				

Código no administrado a administrado transición de código en la misma DLL

En este escenario, puede haber unmanaged métodos (marcados con # pragma unmanaged ) llamara métodos en un componente administrado en la misma DLL, como se muestra en la sección "Más información" de este artículo. Utilice uno de los métodos siguientes para resolver este problema específico:

Solución 1

Convertir el puntero de función como un delegado y utilice ese delegado. Debido a que no puede utilizar P/Invoke en la misma DLL, crear un contenedor DLL que le ayuda a calcular referencias de un delegado para un puntero a función. Esta función exportada devuelve la dirección del delegado que se le pasa. En el siguiente ejemplo de código es un ejemplo de esta solución provisional:
//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;
}
				
el código de ejemplo siguiente es para las extensiones administradas de C++ ensamblado que utiliza el anterior 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();
     }
}
				

Solución 2

Dividir su ensamblado MEC ++ en dos archivos DLL, uno que contiene los componentes administrados sólo y otros que contiene sólo los componentes no administrados y, a continuación, utilizar P/Invoke como se describe en la solución 2 del escenario 1.

Estado

Microsoft ha confirmado que se trata de un problema de los productos de Microsoft enumerados al principio de este artículo.

Más información

El problema es más frecuente si el host o la aplicación de cliente debe descargar cargar AppDomain y la aplicación contiene transiciones de código no administrado a código administrado que utilizan componentes MEC ++ y IJW. ASP.NET es un buen ejemplo de tal un host. En ASP.NET, los eventos que pueden desencadenar un evento de descarga de AppDomain pueden ser cualquier cosa crucen un umbral de uso de memoria a tocar determinados archivos (por ejemplo, Machine.config).

Pasos para reproducir este comportamiento

En este ejemplo, una aplicación ASP.NET que llama a un componente MEC ++, y este componente tiene un puntero a función que señala a uno de los métodos en el componente MEC ++. El componente pasa el puntero de función a uno de los siguientes:
  • una función exportada una DLL no administrada
  • un método no administrado en la misma DLL
El código no administrado crea una devolución de llamada mediante el puntero de función que se recibió desde el componente MEC ++.

En las situaciones siguientes, es posible que, antes de la función no administrada, se invoca el puntero de función, el original en el que se cargará la DLL se descarga AppDomain. En estas condiciones, el código no administrado aún hace referencia el AppDomain original y intenta llamar a código administrado en ese contexto.
  • código no administrado a administrado transición de código en dos archivos DLL

    Llamar a una función DLL no administrada exportada desde MEC ++ ensamblado en una de las maneras siguientes:
    • mediante el uso de IJW
    • utilizando P/Invoke
    El código de ejemplo siguiente utiliza una DLL no administrada (Win32.dll) que exporta un método.
    //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;
    }
    					
    de llamar un ensamblado de C++ administrado puede a este método mediante IJW vinculando a la Win32.lib, incluyendo el archivo de encabezado correspondiente. En el siguiente ejemplo de código muestra cómo utilizar el método exportado. # 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;
    		}
    	};
    }
    					
  • código no administrado a administrado transición de código en la misma DLL

    En este escenario, el ensamblado MEC ++ contiene los métodos no administrados (marcados con # pragma unmanaged ) que llamar a métodos en un componente MEC ++ en la misma DLL como se muestra en el siguiente ejemplo de código.
    #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();
         }
    }
    					

Referencias

Para obtener más información, visite los siguientes sitios Web de Microsoft Developer Network (MSDN):
Dominios de aplicación
http://msdn2.microsoft.com/en-us/library/cxk374d9(vs.71).aspx?frame=true

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

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

Extensiones administradas para la programación en C++
http://msdn2.microsoft.com/en-us/library/aa712574(vs.71).aspx

Crear aplicaciones Web ASP.NET
http://msdn.microsoft.com/en-us/library/aa719794.aspx

Modo de aislamiento de procesos de trabajo
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/34604f82-9175-4d48-b5ea-1e11f19db5f3.mspx?mfr=true

Propiedades

Id. de artículo: 309694 - Última revisión: jueves, 17 de mayo de 2007 - Versión: 4.7
La información de este artículo se refiere a:
  • Microsoft Visual C++ .NET 2002 Standard
  • Microsoft .NET Framework 1.0
Palabras clave: 
kbmt kbbug kbijw kbmanaged kbpending KB309694 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 309694

Enviar comentarios

 

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