BUG: AppDomainUnloaded ยกเว้นเมื่อคุณใช้จัดการส่วนขยายสำหรับคอมโพเนนต์ c ++ Visual

การแปลบทความ การแปลบทความ
หมายเลขบทความ (Article ID): 309694 - ผลิตภัณฑ์ที่เกี่ยวข้องในบทความนี้
ขยายทั้งหมด | ยุบทั้งหมด

เนื้อหาบนหน้านี้

อาการ

ปัญหานี้เกิดขึ้นเมื่อการเรียกถูกแปลงจากรหัสที่ไม่มีการจัดการรหัสได้รับการจัดการ การรวมโทรศัพท์ unmanaged-เมื่อต้องการจัดการที่ตรงภายใน DLL ที่เดียว ตัวอย่างเช่น ปัญหาอาจเกิดขึ้นเมื่อ MEC + +/ IJW ถูกใช้ใน ASP.NET แอปพลิเคชันได้ ใน ASP.NET เหตุการณ์ต่าง ๆ อาจทำให้โปรแกรมประยุกต์เพื่อที่ถูก reloaded เป็นแบบ AppDomain ใหม่ ถ้าคุณกำลังใช้คอมโพเนนต์ MEC ++ และ IJW ในโปรแกรมประยุกต์นี้ คุณอาจได้รับการAppDomainUnloadExceptionข้อความแจ้งข้อผิดพลาด

สาเหตุ

เป็นส่วนหนึ่งของการใช้งานของ IJW เมื่อโหลด DLL ได้รับการจัดการที่คุณสร้างขึ้น โดยใช้คอมไพเลอร์ c ++ รันไทม์จะสร้าง thunks สำหรับช่วงการเปลี่ยนจากรหัสที่ไม่มีการจัดการกับรหัสที่ได้รับการจัดการ thunks เหล่านี้ประกอบด้วยการอ้างอิงถึง AppDomain โหลด DLL สร้างใหม่อีกใช้งานจริงไม่ครั้ง thunks เหล่านี้ถ้าโหลด DLL อีก ยัง รันไทม์จะไม่ปรับปรุงการอ้างอิงเมื่อ unloads AppDomain ที่เดิม และ DLL โหลดใน AppDomain อื่น

เมื่อโปรแกรมทำการเปลี่ยนภาพจากรหัสที่ไม่มีการจัดการกับรหัสที่ได้รับการจัดการ โปรแกรมใช้ AppDomain ที่ล้าสมัยอ้างอิงการเรียกใช้รหัสที่ได้รับการจัดการ แม้ว่า AppDomain ที่ต้นฉบับจะยังคงโหลด รหัสไม่สามารถเข้าเขตข้อมูลแบบคงที่ได้เนื่องจากเขตข้อมูลเป็น AppDomain เฉพาะ

การหลีกเลี่ยงปัญหา

แก้ไขปัญหาต่อไปนี้จะถูกจัดกลุ่มตามที่สองสถานการณ์:
  • การเปลี่ยนภาพจากรหัสที่ไม่มีการจัดการการได้รับการจัดการรหัสผ่าน DLLs ที่สอง
  • การเปลี่ยนภาพจากรหัสที่ไม่มีการจัดการกับรหัสที่ได้รับการจัดการใน DLL เดียวกัน

รหัสที่ไม่มีการจัดการการจัดการการเปลี่ยนรหัสข้าม DLLs ที่สอง

ใช้อย่างใดอย่างหนึ่งในวิธีการต่อไปนี้เพื่อแก้ไขปัญหานี้

วิธีแก้ปัญหา 1

ไคลเอ็นต์ ASP.NET ทำให้กระบวนการโฮสต์ ASP.NET จะปิด โดย trappingdomainUnloadเหตุการณ์ อย่างไรก็ตาม คุณต้องลงก่อนทะเบียนผู้รับมอบสิทธิ์สำหรับการdomainUnloadเหตุการณ์ โดยให้ทำตามขั้นตอนต่อไปนี้::
  1. ในการApplication_Startวิธีการ ASP.NETโปรแกรมประยุกต์คลา ลงทะเบียนที่ผู้รับมอบสิทธิ์จะถูกเรียกเมื่อ AppDomain unloads
  2. ในการมอบหมายลงทะเบียน ปิด Aspnet_wp.exe กระบวนการ
หมายเหตุ:This workaround causes all of the ASP.NET applications on the computer to restart; the in-process session state data for all of these applications is lost. In Internet Information Service (IIS) 6.0 on a computer that is running Windows 2003 Server, you can configure the program for one application per process mode. For more information about configuing application pools, visit the following Microsoft Web site:
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);
}
				

วิธีแก้ปัญหา 2

Replace all transitions from unmanaged code to managed code with calls through an unmanaged function pointer that you create by using a delegate (which is AppDomain specific). The delegate is marshaled to the unmanaged code by using Platform Invocation Services (P/Invoke) instead of IJW.

For the unmanaged DLL described in the "More Information" section of this article, the following sample code demonstrates how to useP/Invoketo use the callback method:
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;
		}
	};
}
				

Unmanaged Code to Managed Code Transition in the Same DLL

In this scenario, you can have unmanaged methods (marked with#pragma unmanaged) calling methods on a managed component in the same DLL, as shown in the "More Information" section of this article. Use either of the following methods to resolve this specific issue:

วิธีแก้ปัญหา 1

Marshal your function pointer as a delegate and use that delegate. Because you cannot useP/Invokeon the same DLL, create a wrapper DLL that helps you to marshal a delegate to a function pointer. This exported function returns the address of the delegate that is passed to it. The following sample code is an example of this workaround:
//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;
}
				
The following sample code is for the Managed Extensions for C++ assembly that uses the previous 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();
     }
}
				

วิธีแก้ปัญหา 2

Split your MEC++ assembly into two DLLs, one that contains only managed components and other that contains only unmanaged components, and then useP/Invokeas described in workaround 2 of scenario 1.

สถานะ

Microsoft ยืนยันว่าปัญหานี้เป็นปัญหาที่เกิดขึ้นกับผลิตภัณฑ์ของ Microsoft ซึ่งมีการระบุไว้ในส่วนเริ่มต้นของเอกสารนี้

ข้อมูลเพิ่มเติม

The problem is more prevalent if the host or client application must unload and reload AppDomains and the application contains transitions from unmanaged code to managed code that use MEC++ and IJW components. ASP.NET is one good example of such a host. In ASP.NET, the events that can trigger an AppDomain unload event can be anything from crossing a memory usage threshold to touching certain files (for example, Machine.config).

ขั้นตอนในการทบทวนเกิดลักษณะการทำงาน

In this example, you have an ASP.NET application that calls a MEC++ component, and this component has a function pointer that points to one of the methods in the MEC++ component. The component passes the function pointer to one of the following:
  • a function that was exported by an unmanaged DLL
  • an unmanaged method in the same DLL
The unmanaged code then makes a callback by using the function pointer that was received from the MEC++ component.

In the following scenarios, it is possible that, before the unmanaged function invokes the function pointer, the original AppDomain in which the DLL was loaded is unloaded. Under such conditions, the unmanaged code still references the original AppDomain and tries to call to managed code in that context.
  • Unmanaged Code to Managed Code Transition Across Two DLLs

    Call an exported unmanaged DLL function from a MEC++ assembly in one of the following ways:
    • by using IJW
    • by usingP/Invoke
    The following sample code uses an unmanaged DLL (Win32.dll) that exports a method.
    //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;
    }
    					
    A managed C++ assembly can call this method through IJW by linking to the Win32.lib and by including the appropriate header file. The following sample code shows how to use the exported method.
    #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;
    		}
    	};
    }
    					
  • Unmanaged Code to Managed Code Transition in the Same DLL

    In this scenario, the MEC++ assembly contains unmanaged methods (marked with#pragma unmanaged) that call methods on a MEC++ component in the same DLL, as shown in the following sample code.
    #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();
         }
    }
    					

ข้อมูลอ้างอิง

For more information, visit the following Microsoft Developer Network (MSDN) Web sites:
Application Domains
http://msdn2.microsoft.com/en-us/library/cxk374d9(vs.71).aspx?frame=true

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

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

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

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

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

คุณสมบัติ

หมายเลขบทความ (Article ID): 309694 - รีวิวครั้งสุดท้าย: 10 มกราคม 2554 - Revision: 4.0
ใช้กับ
  • Microsoft Visual C++ 2002 Standard Edition
  • Microsoft .NET Framework 1.0
Keywords: 
kbbug kbijw kbmanaged kbpending kbmt KB309694 KbMtth
แปลโดยคอมพิวเตอร์
ข้อมูลสำคัญ: บทความนี้แปลโดยซอฟต์แวร์การแปลด้วยคอมพิวเตอร์ของ Microsoft แทนที่จะเป็นนักแปลที่เป็นบุคคล Microsoft มีบทความที่แปลโดยนักแปลและบทความที่แปลด้วยคอมพิวเตอร์ เพื่อให้คุณสามารถเข้าถึงบทความทั้งหมดในฐานความรู้ของเรา ในภาษาของคุณเอง อย่างไรก็ตาม บทความที่แปลด้วยคอมพิวเตอร์นั้นอาจมีข้อบกพร่อง โดยอาจมีข้อผิดพลาดในคำศัพท์ รูปแบบการใช้ภาษาและไวยากรณ์ เช่นเดียวกับกรณีที่ชาวต่างชาติพูดผิดเมื่อพูดภาษาของคุณ Microsoft ไม่มีส่วนรับผิดชอบต่อความคลาดเคลื่อน ความผิดพลาดหรือความเสียหายที่เกิดจากการแปลเนื้อหาผิดพลาด หรือการใช้บทแปลของลูกค้า และ Microsoft มีการปรับปรุงซอฟต์แวร์การแปลด้วยคอมพิวเตอร์อยู่เป็นประจำ
ต่อไปนี้เป็นฉบับภาษาอังกฤษของบทความนี้:309694

ให้ข้อเสนอแนะ

 

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