程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 關於C#中動態加載AppDomain的問題(1)

關於C#中動態加載AppDomain的問題(1)

編輯:關於C語言

在操作系統中,利用進程可以對正在運行的應用程序進行隔離,每個應用程序被加載到單獨的進程中,並為其分配虛擬內存,進程無法直接 訪問物理內存,只能通過操作系統將虛擬內存映射到物理內存中,並保證進程之間的物理內存不會重疊,但是進程最大的缺點就是效率問題, 尤其是進程的切換開銷很大,而進程間不能共享內存,所以不可能從一個進程通過傳遞指針給另一個進程。

在.NET中出現了一個新的概 念:AppDomain——應用程序域,所有.NET應用程序都需要運行在托管環境中,操作系統能提供的只有進程,因此.NET程序需要通過 AppDomain這個媒介來運行在進程中,同時使用該incheng提供的內存空間,只要是.Net的應用都會運行在某個AppDomain中。 

當我們 運行一個.Net應用程序或者運行庫宿主時,OS會首先建立一個進程,然後會在進程中加載CLR(這個加載一般是通過調用_CorExeMain或者 _CorBindToRuntimeEx方法來實現),在加載CLR時會創建一個默認的AppDomain,它是CLR的運行單元,程序的Main方法就是在這裡執行,這個默 認的AppDomain是唯一且不能被卸載的,當該進程消滅時,默認AppDomain才會隨之消失。

一個進程中可以有多個AppDomain,且它們直 接是相互隔離的,我們的Assembly是不能單獨執行的,它必須被加載到某個AppDomain中,要想卸載一個Assembly就只能卸載其AppDomain。

最近在我所參加的一個項目中要實現這樣一個模塊:定制一個作業管理器,它可以定時的以不同頻率執行某些.Net應用程序或者存儲過 程,這裡的頻率可以是僅一次、每天、每周還是每月進行執行計劃的實施,對於調用存儲過程沒什麼好說的,但是調用.Net應用程序的時候就 需要考慮如下問題:

一旦Assembly被作業管理器的服務器調用,(比如某個執行計劃正好要被執行了),在調用之前會將程序集加載到 默認AppDomain,然後執行,這就有個問題,如果我需要做替換或者刪除Assembly等這些操作的時候,由於Assembly已經被默認AppDomain加載 ,那麼對它的更改肯定是不允許的,它會彈出這樣的錯誤: 

除非你關掉作業管理服務器,然後再操作,顯然這樣做是 很不合理的。

並且默認AppDomain是不能被卸載的,那麼我們該怎麼辦呢,我想到的方法是動態的加載Assembly,新建一個AppDomain, 讓Assembly加載到這個新AppDomain中然後執行,當執行完後卸載這個新的AppDomain即可,方法如下:

1、創建程序集加載類 AssemblyDynamicLoader,該類用來創建新的AppDomain,並生成用來執行.Net程序的RemoteLoader類:

 using System;

    using System.Collections.Generic;
    using System.Globalization;
    using  System.IO;
    using System.Reflection;
    using System.Text;
    using Ark.Log;

     /// <summary>
    /// The local loader.
    /// </summary>
    public  class AssemblyDynamicLoader
    {
        /// <summary>
        /// The log  util.
        /// </summary>
        private static ILog log = LogManager.GetLogger (typeof(AssemblyDynamicLoader));

        /// <summary>
        /// The new  appdomain.
        /// </summary>
        private AppDomain appDomain;

         /// <summary>
        /// The remote loader.
        /// </summary>
        private RemoteLoader remoteLoader;

        /// <summary>
        ///  Initializes a new instance of the <see cref="LocalLoader"/> class.
        ///  </summary>
        public AssemblyDynamicLoader()
        {
             AppDomainSetup setup = new AppDomainSetup();
            setup.ApplicationName =  "ApplicationLoader";
            setup.ApplicationBase =  AppDomain.CurrentDomain.BaseDirectory;
            setup.PrivateBinPath = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "private");
            setup.CachePath =  setup.ApplicationBase;
            setup.ShadowCopyFiles = "true";
             setup.ShadowCopyDirectorIEs = setup.ApplicationBase;

            this.appDomain =  AppDomain.CreateDomain("ApplicationLoaderDomain", null, setup);
            String name =  Assembly.GetExecutingAssembly().GetName().FullName;

            this.remoteLoader = (RemoteLoader) this.appDomain.CreateInstanceAndUnwrap(name, typeof(RemoteLoader).FullName);
        }

         /// <summary>
        /// Invokes the method.
        /// </summary>
         /// <param name="fullName">The full name.</param>
        /// <param  name="className">Name of the class.</param>
        /// <param  name="argsInput">The args input.</param>
        /// <param  name="programName">Name of the program.</param>
        /// <returns>The output  of excuting.</returns>
        public String InvokeMethod(String fullName, String className, String  argsInput, String programName)
        {
            this.remoteLoader.InvokeMethod (fullName, className, argsInput, programName);
            return this.remoteLoader.Output;
         }

        /// <summary>
        /// Unloads this instance.
         /// </summary>
        public void Unload()
        {
             try
            {
                AppDomain.Unload(this.appDomain);
                 this.appDomain = null;
            }
            catch  (CannotUnloadAppDomainException ex)
            {
                log.Error("To  unload assembly error!", ex);
            }
        }
    }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved