BUG: AppDomainUnloaded pengecualian ketika Anda menggunakan berhasil ekstensi untuk komponen Visual C++

Terjemahan Artikel Terjemahan Artikel
ID Artikel: 309694 - Melihat produk di mana artikel ini berlaku.
Perbesar semua | Perkecil semua

Pada Halaman ini

GEJALA

Masalah ini terjadi ketika panggilan yang dibuat dari kode tidak dikelola kode dikelola, termasuk langsung panggilan unmanaged-untuk-berhasil dalam satu DLL. sebagai contoh, masalah dapat terjadi ketika MEC + / IJW digunakan dalam ASP.NET aplikasi. Di ASP.NET, berbagai acara dapat menyebabkan aplikasi akan mengisi ulang menjadi AppDomain baru. Jika Anda menggunakan MEC ++ komponen dan IJW dalam hal ini aplikasi, Anda akan menerima AppDomainUnloadException pesan galat.

PENYEBAB

Sebagai bagian dari pelaksanaan IJW, ketika dikelola DLL bahwa Anda dibuat dengan menggunakan banyak kompiler C++, runtime menciptakan thunks untuk transisi dari unmanaged kode untuk mengelola kode. Thunks ini berisi referensi ke AppDomain di mana DLL beban. Runtime tidak menciptakan kembali thunks ini jika DLL beban lagi; juga, runtime tidak memperbarui referensi ketika AppDomain asli membongkar dan DLL beban dalam AppDomain lain.

Ketika program melakukan transisi dari unmanaged kode untuk mengelola kode, program menggunakan AppDomain ketinggalan jaman referensi untuk menjalankan kode dikelola. Bahkan jika AppDomain asli masih tidak dimuat, kode dapat mengakses statis bidang karena bidang khusus untuk AppDomain.

TEKNIK PEMECAHAN MASALAH

Penyelesaian masalah berikut dikelompokkan menurut dua skenario:
  • Transisi dari unmanaged kode untuk mengelola kode di dua Dll
  • Transisi dari unmanaged kode untuk mengelola kode di sama DLL

Kode tidak dikelola untuk berhasil kode transisi di dua dll

Gunakan salah satu metode berikut untuk menyelesaikan ini khusus masalah.

Pemecahan masalah 1

Untuk ASP.NET klien, memungkinkan ASP.Proses NET host untuk menutup oleh perangkap DomainUnload acara. Namun, Anda harus terlebih dahulu mendaftar delegasi untuk DomainUnload acara. Untuk melakukannya, ikuti langkah-langkah berikut:
  1. Dalam Application_Start metode ASP.NET Aplikasi kelas, mendaftar delegasi disebut ketika AppDomain membongkar.
  2. Dalam delegasi terdaftar, menutup Aspnet_wp.exe proses.
Catatan Pemecahan masalah ini menyebabkan semua ASP.NET aplikasi pada komputer me-restart; data status dalam proses sesi untuk semua ini aplikasi hilang. Dalam layanan IIS (Internet Information) 6.0 pada komputer yang menjalankan Windows 2003 Server, Anda dapat mengkonfigurasi program untuk satu aplikasi per proses modus. Untuk informasi lebih lanjut tentang aplikasi configuing kolam renang, kunjungi Web site Microsoft berikut:
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);
}
				

Pemecahan masalah 2

Mengganti semua transisi dari unmanaged kode untuk mengelola kode dengan panggilan melalui fungsi tidak dikelola pointer yang Anda buat dengan menggunakan delegasi (mana yang AppDomain tertentu). Delegasi mengerahkan kode tidak dikelola dengan menggunakan Platform doa layanan)P/Invoke) alih-alih IJW.

Untuk DLL tidak dikelola dijelaskan dalam Bagian "Informasi selengkapnya" dari artikel ini, berikut contoh kode menunjukkan bagaimana untuk menggunakan P/Invoke untuk menggunakan metode panggilan balik:
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;
		}
	};
}
				

Kode tidak dikelola untuk berhasil kode transisi dalam sama DLL

Dalam skenario ini, Anda dapat memiliki unmanaged metode (ditandai dengan c++ unmanaged) memanggil metode komponen dikelola DLL sama, seperti yang ditunjukkan di bagian "Informasi selengkapnya" artikel ini. Menggunakan salah satu dari berikut metode untuk menyelesaikan masalah ini khusus:

Pemecahan masalah 1

Marsekal Anda penunjuk fungsi sebagai utusan dan menggunakannya delegasi. Karena Anda tidak dapat menggunakan P/Invoke pada sama DLL, membuat pembungkus DLL yang membantu Anda untuk mengumpulkan Mendelegasikan ke penunjuk fungsi. Fungsi ini diekspor kembali alamat delegasi yang dilewatkan ke. Dalam kode contoh berikut adalah contoh pemecahan masalah ini:
//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;
}
				
Dalam kode contoh berikut adalah untuk berhasil ekstensi untuk C++ Majelis yang menggunakan Helper.dll sebelumnya:
#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();
     }
}
				

Pemecahan masalah 2

Membagi Anda MEC ++ Majelis ke dua dll, yang hanya berisi berhasil komponen dan lain yang berisi hanya tidak dikelola komponen, dan kemudian penggunaan P/Invoke seperti yang dijelaskan dalam pemecahan masalah 2 skenario 1.

STATUS

Microsoft telah mengkonfirmasi bahwa ini adalah bug di Microsoft produk yang didaftar pada awal artikel ini.

INFORMASI LEBIH LANJUT

Masalahnya lebih umum jika host atau klien aplikasi harus membongkar dan reload AppDomains dan aplikasi berisi transisi dari unmanaged kode untuk mengelola kode yang menggunakan MEC ++ dan IJW komponen. ASP.NET adalah salah satu contoh yang baik dari sebuah host. Di ASP.NET, peristiwa yang dapat memicu AppDomain membongkar acara bisa apa saja dari persimpangan memori penggunaan ambang batas untuk menyentuh file tertentu (misalnya, Machine.config elemen dari).

Langkah-langkah untuk mereproduksi perilaku

Dalam contoh ini, Anda memiliki ASP.NET aplikasi yang panggilan MEC ++ komponen dan komponen ini memiliki fungsi pointer yang menunjuk ke salah satu metode di MEC ++ komponen. Komponen melewati fungsi pointer ke salah satu dari berikut:
  • fungsi yang diekspor oleh unmanaged DLL
  • metode yang tidak dikelola di sama DLL
Kode tidak dikelola kemudian membuat panggilan balik dengan menggunakan fungsi pointer yang diterima dari MEC ++ komponen.

Di bawah skenario, sangat mungkin bahwa, sebelum memanggil fungsi tidak dikelola fungsi pointer, AppDomain asli di mana DLL dimuat adalah diturunkan. Di bawah kondisi seperti itu, kode tidak dikelola masih referensi asli AppDomain dan mencoba untuk memanggil untuk berhasil kode dalam konteks itu.
  • Kode tidak dikelola untuk berhasil kode transisi di dua dll

    Memanggil fungsi DLL tidak dikelola yang diekspor dari MEC ++ Majelis di salah satu cara berikut:
    • dengan menggunakan IJW
    • dengan menggunakan P/Invoke
    Dalam kode contoh berikut menggunakan unmanaged DLL (Win32.dll) yang ekspor metode.
    //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;
    }
    					
    Dikelola C++ Majelis dapat memanggil metode ini melalui IJW dengan menghubungkan ke Win32.lib dan termasuk file header yang sesuai. Berikut kode contoh menunjukkan bagaimana untuk menggunakan metode diekspor.
    #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;
    		}
    	};
    }
    					
  • Kode tidak dikelola untuk berhasil kode transisi dalam sama DLL

    Dalam skenario ini, Majelis MEC ++ berisi tidak dikelola metode (ditandai dengan c++ unmanaged) yang memanggil metode di sebuah MEC ++ komponen dalam DLL sama, seperti yang ditunjukkan dalam kode contoh berikut.
    #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();
         }
    }
    					

REFERENSI

Untuk informasi lebih lanjut, kunjungi Website Microsoft berikut Situs Web Developer Network (MSDN):
Aplikasi domain
http://msdn2.Microsoft.com/en-us/library/cxk374d9 (vs.71) .aspx? bingkai = true

AppDomain kelas
.aspx http://msdn2.Microsoft.com/en-us/library/System.AppDomain (vs.71)

AppDomainUnloadedException kelas
.aspx http://MSDN.Microsoft.com/en-us/library/System.appdomainunloadedexception (VS.71)

Ekstensi yang dikelola untuk pemrograman C++
.aspx http://msdn2.Microsoft.com/en-us/library/aa712574 (vs.71)

Menciptakan ASP.Aplikasi NET Web
http://MSDN.Microsoft.com/en-us/library/aa719794.aspx

Pekerja proses isolasi Mode
http://www.Microsoft.com/technet/prodtechnol/windowsserver2003/Library/IIS/34604f82-9175-4d48-b5ea-1e11f19db5f3.mspx?mfr=True

Properti

ID Artikel: 309694 - Kajian Terakhir: 24 September 2011 - Revisi: 2.0
Berlaku bagi:
  • Microsoft Visual C++ .NET 2002 Standard Edition
  • Microsoft .NET Framework 1.0
Kata kunci: 
kbbug kbijw kbmanaged kbpending kbmt KB309694 KbMtid
Penerjemahan Mesin
PENTING: Artikel ini diterjemahkan menggunakan perangkat lunak mesin penerjemah Microsoft dan bukan oleh seorang penerjemah. Microsoft menawarkan artikel yang diterjemahkan oleh seorang penerjemah maupun artikel yang diterjemahkan menggunakan mesin sehingga Anda akan memiliki akses ke seluruh artikel baru yang diterbitkan di Pangkalan Pengetahuan (Knowledge Base) dalam bahasa yang Anda gunakan. Namun, artikel yang diterjemahkan menggunakan mesin tidak selalu sempurna. Artikel tersebut mungkin memiliki kesalahan kosa kata, sintaksis, atau tata bahasa, hampir sama seperti orang asing yang berbicara dalam bahasa Anda. Microsoft tidak bertanggung jawab terhadap akurasi, kesalahan atau kerusakan yang disebabkan karena kesalahan penerjemahan konten atau penggunaannya oleh para pelanggan. Microsoft juga sering memperbarui perangkat lunak mesin penerjemah.
Klik disini untuk melihat versi Inggris dari artikel ini:309694

Berikan Masukan

 

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