Good way to preload .NET assembly

16,115

Solution 1

Explicit pre-load in your init is probably still your best option.

a typeof(SomeTypeFromAnotherAssembly) should be enough - along with some opaque method that can't be optimised away; perhaps:

GC.KeepAlive(typeof(SomeTypeFromAnotherAssembly));

This avoids the new. Note that this will be loaded, but not JITted etc.

If you wanted, you could do it on a BG thread:

private static void LoadSomeStuff(object state) {
    GC.KeepAlive(typeof(SomeTypeFromAnotherAssembly));
}
...
ThreadPool.QueueUserWorkItem(LoadSomeStuff);

Solution 2

I believe that Assembly.Load is the way.

During application startup you should locate modules, plug-ins or any other run-time pluggable and load their assemblies into application's domain (AppDomain).

Or another and better option: Why don't you use inversion of control for that?

You can use Castle Windsor for that. Let's say you've 4 forms to load in run-time, so, you can create 4 components of Form class which their implementation are the 4 forms to load during the life-cycle of your program.

How to pre-load with this approach? You simply resolve all dependencies/components that are of type of Form and you got it:

container.ResolveAll<Form>();

Later you'll get a particular form:

container.Resolve<Form>("CustomersForm"); // Just an example

If you don't know inversion of control, comment out and I'll assist you, no problem! :)

Solution 3

I think that the easiest way is to just use the assembly name in Assembly.Load():

System.Reflection.Assembly.Load("ICSharpCode.AvalonEdit");

You can find the assembly name under the reference properties in Visual studio:

assembly name in visual studio

This way you can avoid entering dll file paths etc. I use this to speed up the loading of a dialog that uses this DLL. As soon as the program main window is fully loaded it launches a background thread that just calls Assembly.Load(). When the user opens this dialog the small lag of loading this DLL is gone.

Solution 4

var yourAppPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
Assembly.Load(Path.Combine(yourAppPath, "formAssembly.dll"));

Will that do?

Share:
16,115

Related videos on Youtube

Dyppl
Author by

Dyppl

Updated on May 19, 2022

Comments

  • Dyppl
    Dyppl almost 2 years

    In my app I need to show a form on mouse click. The problem is that the form is in another assembly and because of lazy nature of assembly loading it is likely that the assembly isn't loaded yet when the mouse button is pressed. So what I have is very noticeable pause before the form finally appears.

    I was able to come up with a dumb fix by calling new FormFromAnotherAssembly() in my initialization method. That, of course, took care of things and the pause is no longer there, but it's very ugly. The only thing I like about this solution is that I don't have to mess with paths and assembly names which I have to do if I want to use something like Assembly.Load.

    So, what's the good, robust solution of choice if I want to make sure the assembly is loaded before I actually need it?

    Thanks in advance.

    • user1703401
      user1703401 about 13 years
      You are dismissing a good solution. The only other one is to get a faster hard drive. If you haven't defragged the disk in the past 6 months then now is a good time.
  • Dyppl
    Dyppl about 13 years
    That's what I call "messing with paths and assembly names", so no, it won't do
  • jgauffin
    jgauffin about 13 years
    It will always work as long as the assemblies are in the same folder. So I don't see it as messing.
  • Dyppl
    Dyppl about 13 years
    Also, they are not in the same folder
  • Matías Fidemraizer
    Matías Fidemraizer about 13 years
    Well, think if you're going to have lots of run-time loaded forms. If this isn't the situation, yes, this is overkill for you.
  • Dyppl
    Dyppl about 13 years
    Thank you Marc, but what if I want it loaded AND JITted etc? Because it looks like loading an assembly is only part of the problem and the pause is still there.
  • Marc Gravell
    Marc Gravell about 13 years
    @Dyppl - JIT is relatively quick - I suggest the issue is loading other (downstream) assemblies and loading other resources. If you debug you should be able to see what else loads...
  • Dyppl
    Dyppl about 13 years
    Well, at the moment it's unlikely, but thank you anyway, I'll try your solution when I have the need.
  • Matías Fidemraizer
    Matías Fidemraizer about 13 years
    BTW, why don't you do a hand-made inversion of control, something as simple as put in your application settings the full assembly qualified name of your form, and just do something like YourForm.Preload() - returning the form - which would do Type.GetType(Properties.Settings.Default.FormAssemblyName); ? (that would mean other form's assembly is in the bin directory, but if this isn't your case, just provide the full physical path in settings, and just do an Assembly.Load in your SomeForm.Preload())
  • Dyppl
    Dyppl about 13 years
    Well, yes, unfortunately, the form is a WPF one and drags a lot of crap along with it.
  • Dyppl
    Dyppl about 13 years
    I was hoping for a more elegant solution. Why would I go through all this if the framework knows where to find the form and how to load it? It just doesn't do it until he really needs to, so I wanted to make him need it a little sooner. Of course, I can do all this, but the question was more or less "is there a better way to do it".
  • Matías Fidemraizer
    Matías Fidemraizer about 13 years
    Can you clarify if this form assembly is referenced? Or it's just placed in the bin directory?
  • Marc Gravell
    Marc Gravell about 13 years
    @Dyppl then you may have no choice to spin up a form to prep everything; and you should probably only do that from the UI thread.
  • Dyppl
    Dyppl about 13 years
    thanks, I don't know what what I'll end up doing, but your solution was good for the task I described in question, so I'm marking it
  • Matías Fidemraizer
    Matías Fidemraizer about 13 years
    oh, then, maybe you've another simple option: Asssembly.GetReferencedAssemblies. This method returns all referenced assemblies by one. That's you can automatically pre-load all referenced assemblies as your application start invoking Assembly.Load(AssemblyName). It's almost the same thing, but you avoid literals, because app assembly will be retrieved with Assembly.GetExecutingAssembly.
  • Andreas Reiff
    Andreas Reiff almost 12 years
    Nice solution. Does not work for me with "official" GAC assemblies. Actually.. what I want is the "xxx loaded" message in the Debug Output window in VS, it does not appear for GC.KeepAlive(typeof(System.Runtime.Remoting.RemotingServices‌​)); (to load System.Runtime.Remoting.dll)
  • Hugh W
    Hugh W about 11 years
    I think this may achieve the same thing while being slightly more readable: stackoverflow.com/a/4181676/1688738 (I'm not sure if this depends on you having written a static initializer but somehow I doubt it does).
  • fjch1997
    fjch1997 over 3 years
    @MarcGravell I think you can spin up a second STA thread to load the form in the background, with the window state as hidden.