日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

AppDomain,应用程序域

發(fā)布時(shí)間:2025/7/14 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AppDomain,应用程序域 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
AppDomain是CLR的運(yùn)行單元,它可以加載Assembly、創(chuàng)建對(duì)象以及執(zhí)行程序。
AppDomain是CLR實(shí)現(xiàn)代碼隔離的基本機(jī)制。 每一個(gè)AppDomain可以單獨(dú)運(yùn)行、停止;每個(gè)AppDomain有自己默認(rèn)的異常處理;
一個(gè)AppDomain的運(yùn)行失敗不會(huì)影響到其他的AppDomain。
CLR在被CLR Host(windows shell or InternetExplorer or SQL Server)加載后,要?jiǎng)?chuàng)建一個(gè)默認(rèn)的AppDomain,程序的入口點(diǎn) (Main方法)就是在這個(gè)默認(rèn)的AppDomain中執(zhí)行。
1.AppDomain vs 進(jìn)程
AppDomain被創(chuàng)建在進(jìn)程中,一個(gè)進(jìn)程內(nèi)可以有多個(gè)AppDomain。一個(gè)AppDomain只能屬于一個(gè)進(jìn)程。
2.AppDomain vs 線程
其實(shí)兩者本來(lái)沒(méi)什么好對(duì)比的。AppDomain是個(gè)靜態(tài)概念,只是限定了對(duì)象的邊界;線程是個(gè)動(dòng)態(tài)概念,它可以運(yùn)行在不同的
AppDomain。
一個(gè)AppDomain內(nèi)可以創(chuàng)建多個(gè)線程,但是不能限定這些線程只能在本AppDomain內(nèi)執(zhí)行代碼。
CLR中的System.Threading.Thread對(duì)象其實(shí)是個(gè)soft thread,它并不能被操作系統(tǒng)識(shí)別;操作系統(tǒng)能識(shí)別的是hard thread。
一個(gè)soft thread只屬于一個(gè)AppDomain,穿越AppDomain的是hard thread。當(dāng)hard thread訪問(wèn)到某個(gè)AppDomain時(shí),一個(gè) AppDomain就會(huì)為之產(chǎn)生一個(gè)soft thread。 hard thread有thread local storage(TLS),這個(gè)存儲(chǔ)區(qū)被CLR用來(lái)存儲(chǔ)這個(gè)hard thread當(dāng)前對(duì)應(yīng)的AppDomain引用以及soft thread引用。當(dāng)一個(gè)hard thread穿越到另外一個(gè)AppDomain時(shí),TLS中的這些引用也會(huì)改變。
當(dāng)然這個(gè)說(shuō)法很可能是和CLR的實(shí)現(xiàn)相關(guān)的。
3.AppDomain vs Assembly
Assembly是.Net程序的基本部署單元,它可以為CLR提供用于識(shí)別類型的元數(shù)據(jù)等等。Assembly不能單獨(dú)執(zhí)行,它必須被加載到 AppDomain中,然后由AppDomain創(chuàng)建程序集中的對(duì)象。
一個(gè)Assembly可以被多個(gè)AppDomain加載,一個(gè)AppDomain可以加載多個(gè)Assembly。 每個(gè)AppDomain引用到某個(gè)類型的時(shí)候需要把相應(yīng)的assembly在各自的AppDomain中初始化。因此,每個(gè)AppDomain會(huì)單獨(dú)保持一 個(gè)類的靜態(tài)變量。
4.AppDomain vs 對(duì)象
任何對(duì)象只能屬于一個(gè)AppDomain。AppDomain用來(lái)隔離對(duì)象,不同AppDomain之間的對(duì)象必須通過(guò)Proxy(reference type)或者 Clone(value type)通信。 引用類型需要繼承System.MarshalByRefObject才能被Marshal/UnMarshal(Proxy)。
值類型需要設(shè)置Serializable屬性才能被Marshal/UnMarshal(Clone)。
5.AppDomain vs Assembly Code
AppDomain和程序集的源代碼是什么關(guān)系呢?每個(gè)程序集的代碼會(huì)分別裝載到各個(gè)AppDomain中?
首先我們要把程序集分3類
1.mscorlib,這是每個(gè).net程序都要引用到的程序集。
2.GAC,這個(gè)是強(qiáng)命名的公用程序集,可以被所有的.net程序引用。
3.Assembly not in GAC,這是普通的assembly,可以不是強(qiáng)命名,不放到GAC中。 啟動(dòng)CLR,進(jìn)入entry point時(shí)可以設(shè)置LoaderOptimization屬性:
[LoaderOptimization(LoaderOptimization.MultiDomain]
static void Main()
{...}
LoaderOptimization屬性可以設(shè)置三個(gè)不同的枚舉值,來(lái)設(shè)置針對(duì)前面說(shuō)的三種程序集的代碼存放以及訪問(wèn)方式。
LoaderOptimization Enumeration/Attribute
Value Expected Domains in Process Each Domain Expected to Run ... Code for MSCORLIB Code for Assemblies in GAC Code for Assemblies not in GAC SingleDomain One N/A Per-process Per-domain Per-domain MultiDomain Many Same Program Per-process Per-process Per-process MultiDomainHost Many Different Programs Per-process Per-process Per-domain
1.SingleDomain,由于只啟動(dòng)一個(gè)AppDomain,那么code就被直接裝載到了AppDomain中,訪問(wèn)靜態(tài)變量更快捷。 2.MultiDomain,所有的Assembly代碼是進(jìn)程級(jí)別的,因此所有的AppDomain只訪問(wèn)一份代碼。這大大減少了程序占用的內(nèi)存,但 是由于程序集的靜態(tài)變量仍然在各個(gè)AppDomain中,因此代碼訪問(wèn)靜態(tài)變量需要先得到AppDomain的引用再進(jìn)行轉(zhuǎn)換,速度會(huì)受到 影響。 3.MultiDomainHost,只有GAC代碼是共享的,非GAC的Assembly依然會(huì)加載到被使用的AppDomain中,這樣提高了靜態(tài)變量的訪問(wèn) 速度,當(dāng)然也增加了程序占用的內(nèi)存。? 不管是哪種方式,mscorlib始終是process級(jí)別的,即只有一份mscorlib代碼在內(nèi)存中。

C#中動(dòng)態(tài)加載和卸載DLL

在C++中加載和卸載DLL是一件很容易的事,LoadLibrary和FreeLibrary讓你能夠輕易的在程序中加載DLL,然后在任何地方卸載。在C#中我們也能使用Assembly.LoadFile實(shí)現(xiàn)動(dòng)態(tài)加載DLL,但是當(dāng)你試圖卸載時(shí),你會(huì)很驚訝的發(fā)現(xiàn)Assembly沒(méi)有提供任何卸載的方法。這是由于托管代碼的自動(dòng)垃圾回收機(jī)制會(huì)做這件事情,所以C#不提供釋放資源的函數(shù),一切由垃圾回收來(lái)做。

這引發(fā)了一個(gè)問(wèn)題,用Assembly加載的DLL可能只在程序結(jié)束的時(shí)候才會(huì)被釋放,這也意味著在程序運(yùn)行期間無(wú)法更新被加載的DLL。而這個(gè)功能在某些程序設(shè)計(jì)時(shí)是非常必要的,考慮你正在用反射機(jī)制寫(xiě)一個(gè)查看DLL中所有函數(shù)詳細(xì)信息的程序,程序提供一個(gè)菜單讓用戶可以選擇DLL文件,這時(shí)就需要讓程序能夠卸載DLL,否則一旦用戶重新得到新版本DLL時(shí),必須要重新啟動(dòng)程序,重新選擇加載DLL文件,這樣的設(shè)計(jì)是用戶無(wú)法忍受的。

C#也提供了實(shí)現(xiàn)動(dòng)態(tài)卸載DLL的方法,通過(guò)AppDomain來(lái)實(shí)現(xiàn)。AppDomain是一個(gè)獨(dú)立執(zhí)行應(yīng)用程序的環(huán)境,當(dāng)AppDomain被卸載的時(shí)候,在該環(huán)境中的所有資源也將被回收。關(guān)于AppDomain的詳細(xì)資料參考MSDN。下面是使用AppDomain實(shí)現(xiàn)動(dòng)態(tài)卸載DLL的代碼,

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Reflection;
namespace UnloadDll
{
class Program
{
static void Main(string[] args)
{
string callingDomainName = AppDomain.CurrentDomain.FriendlyName;//Thread.GetDomain().FriendlyName;
Console.WriteLine(callingDomainName);
AppDomain ad = AppDomain.CreateDomain("DLL Unload test");
ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap(@"UnloadDll.exe", "UnloadDll.ProxyObject");
obj.LoadAssembly();
obj.Invoke("TestDll.Class1", "Test", "It's a test");
AppDomain.Unload(ad);
obj = null;
Console.ReadLine();
}
}
class ProxyObject : MarshalByRefObject
{
Assembly assembly = null;
public void LoadAssembly()
{
assembly = Assembly.LoadFile(@"TestDLL.dll");
}
public bool Invoke(string fullClassName, string methodName, params Object[] args)
{
if(assembly == null)
return false;
Type tp = assembly.GetType(fullClassName);
if (tp == null)
return false;
MethodInfo method = tp.GetMethod(methodName);
if (method == null)
return false;
Object obj = Activator.CreateInstance(tp);
method.Invoke(obj, args);
return true;
}
}
}

注意:

1. 要想讓一個(gè)對(duì)象能夠穿過(guò)AppDomain邊界,必須要繼承MarshalByRefObject類,否則無(wú)法被其他AppDomain使用。

2. 每個(gè)線程都有一個(gè)默認(rèn)的AppDomain,可以通過(guò)Thread.GetDomain()來(lái)得到

總結(jié)

以上是生活随笔為你收集整理的AppDomain,应用程序域的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。