2011-02-04 13 views
19

En mi aplicación, necesito mostrar un formulario con un clic del mouse. El problema es que el formulario está en otro ensamblaje y, debido a la naturaleza perezosa de la carga del ensamblaje, es probable que el ensamblaje aún no esté cargado cuando se presiona el botón del mouse. Entonces, lo que tengo es una pausa muy notable antes de que aparezca finalmente la forma.Una buena forma de precargar el ensamblado .NET

Pude encontrar una solución tonta llamando al new FormFromAnotherAssembly() en mi método de inicialización. Eso, por supuesto, se hizo cargo de las cosas y la pausa ya no está allí, pero es muy feo. Lo único que me gusta de esta solución es que no tengo que meterme con rutas y nombres de ensamblaje, lo que tengo que hacer si quiero usar algo como Assembly.Load.

Entonces, ¿cuál es la buena y robusta solución de elección si quiero asegurarme de que el ensamblaje esté cargado antes de que realmente lo necesite?

Gracias de antemano.

+0

Estás descartando una buena solución. El único otro es obtener un disco duro más rápido. Si no ha desfragmentado el disco en los últimos 6 meses, ahora es un buen momento. –

+0

@ Hans Passant: ¿cuál? – Dyppl

Respuesta

19

La precarga explícita en tu init probablemente sea todavía tu mejor opción.

a typeof(SomeTypeFromAnotherAssembly) debe ser suficiente, junto con algún método opaco que no se puede optimizar; quizás:

GC.KeepAlive(typeof(SomeTypeFromAnotherAssembly)); 

Esto evita el new. Tenga en cuenta que esta será cargado , pero no compilados JIT etc.

Si quisiera, podría hacerlo en un hilo BG:

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

Gracias Marc, pero ¿y si quiero que se cargue Y JATE, etc.? Porque parece que cargar un ensamblaje es solo parte del problema y la pausa aún está allí. – Dyppl

+0

@Dyppl - JIT es relativamente rápido: sugiero que el problema es cargar * otros * ensambles (descendentes) y cargar otros recursos. Si depura, debería poder ver qué más carga ... –

+0

Bueno, sí, desafortunadamente, la forma es de WPF y arrastra una gran cantidad de basura junto con ella. – Dyppl

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

¿Qué hacer?

+2

Eso es lo que llamo "jugar con rutas y nombres de ensamblado", por lo que no, no funcionará – Dyppl

+0

Siempre funcionará siempre que los ensamblajes estén en la misma carpeta. Entonces no lo veo como un desastre. – jgauffin

+0

Además, no están en la misma carpeta – Dyppl

2

Creo que Assembly.Load es el camino.

Durante el inicio de la aplicación, debe ubicar los módulos, complementos o cualquier otro tiempo de funcionamiento enchufable y cargar sus ensamblajes en el dominio de la aplicación (AppDomain).

u otra y mejor opción: ¿Por qué no usa la inversión de control para eso?

Puedes usar Castle Windsor para eso. Supongamos que tiene 4 formularios para cargar en tiempo de ejecución, por lo tanto, puede crear 4 componentes de la clase Form, cuya implementación son los 4 formularios que se cargarán durante el ciclo de vida de su programa.

¿Cómo precargar con este enfoque? Sólo tiene que resolver todas las dependencias/componentes que son de tipo de formulario y lo tienes:

container.ResolveAll<Form>(); 

tarde obtendrá una forma particular:

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

Si usted no sabe la inversión de control , comenta y te ayudaré, ¡no hay problema! :)

+0

Esto se parece a una exageración para mi problema, pero gracias – Dyppl

+0

Bueno, piense si va a tener muchos formularios cargados en tiempo de ejecución. Si esta no es la situación, sí, esto es demasiado para ti. –

+0

Bueno, por el momento es poco probable, pero gracias de todos modos, intentaré su solución cuando lo necesite. – Dyppl

0

Creo que la manera más fácil es simplemente usar el nombre del ensamblado en el ensamblaje.Load():

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

se puede encontrar el nombre de ensamblado en las propiedades de referencia en el estudio visual:

assembly name in visual studio

esta manera se puede evitar entrar en las rutas de archivos DLL, etc. Lo utilizo para la velocidad la carga de un diálogo que usa esta DLL. Tan pronto como la ventana principal del programa esté completamente cargada, inicia un hilo de fondo que solo llama a Assembly.Load(). Cuando el usuario abre este cuadro de diálogo, el pequeño retraso de cargar esta DLL se ha ido.

Cuestiones relacionadas