web-dev-qa-db-ja.com

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で十分ですか?
  • ガベージコレクターを呼び出して、アセンブリに割り当てられたリソースを再利用する明示的な方法はありますか?
50
prosseek

残念ながら、一度ロードされたアセンブリをアンロードすることはできません。ただし、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()を再度呼び出して待機する必要があります。

34
slfan

別の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);
68

LoadFrom()またはLoadFile()を使用する代わりに、File.ReadAllBytes()Loadを使用できます。これにより、アセンブリファイルは使用されませんが、それを読み取り、読み取りデータが使用されます。

コードは次のようになります

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

From here ファイルに含まれるすべてのドメインがアンロードされない限り、ファイルをアンロードできません。

お役に立てれば。:)

32
Hardik

現在のAppDomainからアセンブリをアンロードすることはできません。ただし、新しいAppDomainを作成し、そこにアセンブリをロードし、新しいAppDomain内でコードを実行してからアンロードできます。次のリンクを確認してください: [〜#〜] msdn [〜#〜]

4

残念ながら、アセンブリをアンロードすることはできません。さらに、appdomainsを使用している場合は、メインアプリケーションのapi /アセンブリと通信できなくなります。

問題に関する最良の説明はここにあります:

スクリプトホスティングガイドライン http://www.csscript.net/help/Scr​​ipt_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を使用するのは現時点では唯一の方法ですが、残念ながらRAMとディスク領域を消費します。

コードサンプルの実行方法-ここから参照できます。

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

そして、ここにデモビデオがあります:

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

0
TarmoPikaro

依存アセンブリなしで初期アセンブリのみをロードする場合は、AppDomainでAssembly.LoadFileを使用し、完了時にAppDomainをアンロードできます。

アセンブリをロードして操作するローダークラスを作成します。

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);
}
0
Edward Brey