簡體   English   中英

卸載使用 Assembly.LoadFrom() 加載的程序集

[英]Unloading the Assembly loaded with Assembly.LoadFrom()

在加載 dll 后,我需要檢查運行 GetTypes() 的時間量。 代碼如下。

Assembly assem = Assembly.LoadFrom(file);
sw = Stopwatch.StartNew();
var types1 = assem.GetTypes();
sw.Stop();
double time1 = sw.Elapsed.TotalMilliseconds;

我想卸載並重新加載 dll 以檢查再次運行 GetTypes() 所花費的時間。

  • 我怎樣才能卸載它? assem = null夠好嗎?
  • 有沒有一種明確的方法來調用垃圾收集器來回收分配給 assem 的資源?

您可以使用另一個 AppDomain 嗎?

AppDomain dom = AppDomain.CreateDomain("some");     
AssemblyName assemblyName = new AssemblyName();
assemblyName.CodeBase = pathToAssembly;
Assembly assembly = dom.Load(assemblyName);
Type [] types = assembly.GetTypes();
AppDomain.Unload(dom);

您可以將LoadFile.ReadAllBytes()一起使用,而不是使用LoadFrom()LoadFile() ) 。 有了這個,它不使用程序集文件,但會讀取它並使用讀取數據。

您的代碼將如下所示

Assembly assem = Assembly.Load(File.ReadAllBytes(filePath));
sw = Stopwatch.StartNew();
var types1 = assem.GetTypes();
sw.Stop();
double time1 = sw.Elapsed.TotalMilliseconds;

這里我們無法卸載文件,除非它包含的所有域都被卸載。

希望這可以幫助。:)

不幸的是,一旦加載了程序集,您就無法卸載它。 但是您可以卸載 AppDomain。 您可以做的是創建一個新的 AppDomain (AppDomain.CreateDomain(...) ),將程序集加載到此 appdomain 中以使用它,然后在需要時卸載 AppDomain。 卸載 AppDomain 時,將卸載所有已加載的程序集。 (見參考

要調用垃圾收集器,您可以使用

GC.Collect(); // collects all unused memory
GC.WaitForPendingFinalizers(); // wait until GC has finished its work
GC.Collect();

GC 在后台線程中調用終結器,這就是為什么您必須等待並再次調用 Collect() 以確保您刪除了所有內容。

您不能從當前 AppDomain 中卸載程序集。 但是您可以創建新的 AppDomain,將程序集加載到其中,在新的 AppDomain 中執行一些代碼,然后將其卸載。 檢查以下鏈接: MSDN

如果您只想加載初始程序集而不加載其任何依賴程序集,則可以在 AppDomain 中使用Assembly.LoadFile ,然后在完成后卸載 AppDomain。

創建加載程序 class 以加載和使用程序集:

class Loader : MarshalByRefObject
{
    public void Load(string file)
    {
        var assembly = Assembly.LoadFile(file);
        // Do stuff with the assembly.
    }
}

在單獨的應用程序域中運行加載程序,如下所示:

var domain = AppDomain.CreateDomain(nameof(Loader), AppDomain.CurrentDomain.Evidence, new AppDomainSetup { ApplicationBase = Path.GetDirectoryName(typeof(Loader).Assembly.Location) });
try {
    var loader = (Loader)domain.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName);
    loader.Load(myFile);
} finally {
    AppDomain.Unload(domain);
}

不幸的是,程序集無法卸載,而且 - 如果您使用 appdomains - 那么它將阻止您與主應用程序的 api/程序集進行通信。

可以在此處找到有關問題的最佳描述:

腳本托管指南http://www.csscript.net/help/Script_hosting_guideline_.html

如果您想在不與主應用程序通信的情況下運行 C# 代碼 - 那么最好的方法是集成 C# 腳本 API:

https://github.com/oleg-shilo/cs-script/tree/master/Source/deployment/samples/Hosting/Legacy%20Samples/CodeDOM/Modifying%20script%20without%20restart

對於集成,您將需要以下軟件包:

C# 腳本: http://www.csscript.net/CurrentRelease.html

Visual Studio 擴展: https://marketplace.visualstudio.com/items?itemName=oleg-shilo.cs-script

但是,如果您想從 C# 腳本與您的應用程序進行通信 - 那么使用相同的 appDomain 並不斷更改程序集名稱是目前唯一的方法 - 但不幸的是,這會占用內存和磁盤空間。

代碼示例如何做到這一點可以做到 - 可以從這里找到:

https://github.com/tapika/cppscriptcore CsScriptHotReload.sln

這是演示視頻:

https://drive.google.com/open?id=1jOECJj0_UPNdllwF4GWb5OMybWPc0PUV

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM