1. 程式人生 > >應用程序域-學習

應用程序域-學習

shared 開啟 app 其它 object .html www 原來 不能

原文:https://www.cnblogs.com/1996V/p/9037603.html

應用程序域

傳統非托管程序是直接承載在Windows進程中,托管程序是承載在.NET虛擬機CLR上的,而在CLR中管控的這部分資源中,被分成了一個個邏輯上的分區,這個邏輯分區被稱為應用程序域,是.NET Framework中定義的一個概念。
因為堆內存的構建和刪除都通過GC去托管,降低了人為出錯的幾率,在此特性基礎上.NET強調在一個進程中通過CLR強大的管理建立起對資源邏輯上的隔離區域,每個區域的應用程序互不影響,從而讓托管代碼程序的安全性和健壯性得到了提升。

熟悉程序集加載規則和AppDomain是在.NET技術下進行插件編程的前提。AppDomain這部分概念並不復雜。
當啟動一個托管程序時,最先啟動的是CLR,在這過程中會通過代碼初始化三個邏輯區域,最先是SystemDomain系統程序域,然後是SharedDoamin共享域,最後是{程序集名稱}Domain默認域。

系統程序域裏維持著一些系統構建項,我們可以通過這些項來監控並管理其它應用程序域等。共享域存放著其它域都會訪問到的一些信息,當共享域初始化完畢後,會自動加載mscorlib.dll程序集至該共享域。而默認域則用儲存自身程序集的信息,我們的主程序集就會被加載至這個默認域中,執行程序入口方法,在沒有特殊動作外所產生的一切耗費都發生在該域。

我們可以在代碼中創建和卸載應用程序域,域與域之間有隔離性,掛掉A域不會影響到B域,並且對於每一個加載的程序集都要指定域的,沒有在代碼中指定域的話,默認都是加載至默認域中。
AppDomain可以想象成組的概念,AppDomain包含了我們加載的一組程序集。我們通過代碼卸載AppDomain,即同時卸載了該AppDomain中所加載的所有程序集在內存中的相關區域。

AppDomain的初衷是邊緣隔離,它可以讓程序不重新啟動而長時間運行,圍繞著該概念建立的體系從而讓我們能夠使用.NET技術進行插件編程。

當我們想讓程序在不關閉不重新部署的情況下添加一個新的功能或者改變某一塊功能,我們可以這樣做:將程序的主模塊仍默認加載至默認域,再創建一個新的應用程序域,然後將需要更改或替換的模塊的程序集加載至該域,每當更改和替換的時候直接卸載該域即可。 而因為域的隔離性,我在A域和B域加載同一個程序集,那麽A域和B域就會各存在內存地址不同但數據相同的程序集數據。

跨邊界訪問

事實上,在開發中我們還應該註意跨域訪問對象的操作(即在A域中的程序集代碼直接調用B域中的對象)是與平常編程中有所不同的,一個域中的應用程序不能直接訪問另一個域中的代碼和數據,對於這樣的在進程內跨域訪問操作分兩類。

一是按引用封送,需要繼承System.MarshalByRefObject,傳遞的是該對象的代理引用,與源域有相同的生命周期。
二是按值封送,需要被[Serializable]標記,是通過序列化傳遞的副本,副本與源域的對象無關。
無論哪種方式都涉及到兩個域直接的封送、解封,所以跨域訪問調用不適用於過高頻率。
(比如,原來你是這樣調用對象: var user=new User(); 現在你要這樣:var user=(User){應用程序域對象實例}.CreateInstanceFromAndUnwrap("Model.dll","Model.User"); )

值得註意的是,應用程序域是對程序集的組的劃分,它與進程中的線程是兩個一橫一豎,方向不一樣的概念,不應該將這2個概念放在一起比較。我們可以通過Thread.GetDomain來查看執行線程所在的域。
應用程序域在類庫中是System.AppDomain類,部分重要的成員有:

技術分享圖片
        獲取當前 System.Threading.Thread 的當前應用程序域
        public static AppDomain CurrentDomain { get; }
        使用指定的名稱新建應用程序域
        public static AppDomain CreateDomain(string friendlyName);
        卸載指定的應用程序域。
        public static void Unload(AppDomain domain);
        指示是否對當前進程啟用應用程序域的 CPU 和內存監視,開啟後可以根據相關屬性進行監控
        public static bool MonitoringIsEnabled { get; set; }
        當前域托管代碼拋出異常時最先發生的一個事件,框架設計中可以用到
        public event EventHandler<FirstChanceExceptionEventArgs> FirstChanceException;
        當某個異常未被捕獲時調用該事件,如代碼裏只catch了a異常,實際產生的是 b異常,那麽b異常就沒有捕捉到。
        public event UnhandledExceptionEventHandler UnhandledException;
        為指定的應用程序域屬性分配指定值。該應用程序域的局部存儲值,該存儲不劃分上下文和線程,均可通過GetData獲取。
        public void SetData(string name, object data);
        如果想使用托管代碼來覆蓋CLR的默認行為https://msdn.microsoft.com/zh-cn/library/system.appdomainmanager(v=vs.85).aspx
        public AppDomainManager DomainManager { get; }
        返回域的配置信息,如在config中配置的節點信息
        public AppDomainSetup SetupInformation { get; }
技術分享圖片

應用程序域: https://docs.microsoft.com/zh-cn/dotnet/framework/app-domains/application-domains

AppDomain和AppPool

註意:此處的AppDomain應用程序域 和 IIS中的AppPool應用程序池 是2個概念,AppPool是IIS獨有的概念,它也相當於一個組的概念,對網站進行劃組,然後對組進行一些如進程模型、CPU、內存、請求隊列的高級配置。

應用程序域-學習