58 votes

Déchargement de l'assemblage chargé avec Assembly.LoadFrom()

J'ai besoin de vérifier le temps nécessaire pour exécuter GetTypes() après le chargement de la dll. Le code est le suivant.

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

J'aimerais décharger et recharger la dll pour vérifier le temps à passer pour exécuter GetTypes() à nouveau.

  • Comment puis-je le décharger ? assem = null est suffisant ?
  • Existe-t-il un moyen explicite d'appeler le ramasseur de déchets pour récupérer la ressource allouée à assem ?

72voto

Rene de la garza Points 484

Pouvez-vous utiliser un autre 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);

46voto

Hardik Points 401

Au lieu d'utiliser LoadFrom() o LoadFile() vous pouvez utiliser Load con File.ReadAllBytes() . Avec cela, il n'utilise pas le fichier d'assemblage mais le lira et utilisera les données lues.

Votre code sera alors le suivant

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

De aquí Nous ne pouvons pas décharger le fichier si tous les domaines qu'il contient ne sont pas déchargés.

J'espère que cela vous aidera :)

38voto

slfan Points 4541

Malheureusement, vous ne pouvez pas décharger un assemblage une fois qu'il est chargé. Mais vous pouvez décharger un AppDomain. Ce que vous pouvez faire, c'est créer un nouvel AppDomain (AppDomain.CreateDomain(...) ), charger l'assemblage dans cet AppDomain pour travailler avec lui, et ensuite décharger l'AppDomain quand c'est nécessaire. Lors du déchargement de l'AppDomain, tous les assemblages qui ont été chargés seront déchargés. (Voir référence )

Pour appeler le ramasseur de déchets, vous pouvez utiliser

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

GC appelle les finaliseurs dans un thread d'arrière-plan, c'est pourquoi vous devez attendre et appeler Collect() à nouveau pour vous assurer que vous avez tout supprimé.

4voto

Yuriy Rozhovetskiy Points 14033

Vous ne pouvez pas décharger l'assemblage de l'AppDomain actuel. Mais vous pouvez créer un nouvel AppDomain, y charger des assemblages, exécuter du code dans le nouvel AppDomain et ensuite le décharger. Vérifiez le lien suivant : MSDN

3voto

Edward Brey Points 8771

Si vous voulez seulement charger l'assemblage initial sans aucun de ses assemblages dépendants, vous pouvez utiliser Assembly.LoadFile dans un AppDomain, et ensuite décharger l'AppDomain quand c'est fait.

Créez une classe de chargeur pour charger et travailler avec l'assemblage :

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

Exécutez le chargeur dans un domaine d'application séparé comme ceci :

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);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X