2008-11-04 19 views
8

Tengo una aplicación WinForms (Estoy usando VB) que se puede minimizar en la bandeja del sistema. Utilicé los métodos "hackish" descritos en varias publicaciones utilizando NotifyIcon y jugando con el evento Form_Resize..NET Minimizar en la bandeja Y Minimizar los recursos necesarios

Todo funciona bien estéticamente, pero los recursos y la memoria utilizados no se ven afectados. Quiero poder minimizar los recursos al minimizar a la bandeja del sistema, al igual que Visual Studio. Si está codificando en Visual Studio, el uso de la memoria puede subir (según el tamaño del proyecto) a más de 500 MB, pero al minimizar Visual Studio en la barra de tareas, la memoria disminuye drásticamente a (lo que asumo) es la cantidad mínima .

¿Alguien tiene alguna pista sobre cómo lograr esto?

Aquí hay una breve descripción de la aplicación, si alguien la considera relevante: Tengo un formulario de Windows con un ListView que contiene órdenes de trabajo para mi departamento de TI. La aplicación tiene un "oyente" que notifica cuando se envía una nueva orden de trabajo. Entonces, cuando la aplicación se ejecuta en la bandeja del sistema, todo lo que hago es comparar el recuento de elementos en el ListView con un recuento de filas en una tabla SQL cada dos minutos.

EDITAR: Para ser más específicos, un formulario de Windows intrínsecamente tiene hilos y recursos que se utilizan mediante los controles, cuando el formulario es invisible (en la bandeja del sistema) estos recursos todavía se están utilizando. ¿Qué puedo hacer para minimizar estos recursos, salvo eliminar todos los controles y volver a dibujarlos cuando se restaura el formulario?

+0

está ejecutando su aplicación fuera de VS, ¿correcto? Inflará el uso de memoria de tu aplicación. – StingyJack

Respuesta

8

Calling MiniMizeMemory() van a hacer una recolección de basura, recortar el tamaño del proceso de trabajo, a continuación, compactar el montón de proceso.

public static void MinimizeMemory() 
{ 
    GC.Collect(GC.MaxGeneration); 
    GC.WaitForPendingFinalizers(); 
    SetProcessWorkingSetSize(
     Process.GetCurrentProcess().Handle, 
     (UIntPtr)0xFFFFFFFF, 
     (UIntPtr)0xFFFFFFFF); 

    IntPtr heap = GetProcessHeap(); 

    if (HeapLock(heap)) 
    { 
     try 
     { 
      if (HeapCompact(heap, 0) == 0) 
      { 
       // error condition ignored 
      } 
     } 
     finally 
     { 
      HeapUnlock(heap); 
     } 
    } 
} 

[DllImport("kernel32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
internal static extern bool SetProcessWorkingSetSize(
    IntPtr process, 
    UIntPtr minimumWorkingSetSize, 
    UIntPtr maximumWorkingSetSize); 

[DllImport("kernel32.dll", SetLastError = true)] 
internal static extern IntPtr GetProcessHeap(); 

[DllImport("kernel32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
internal static extern bool HeapLock(IntPtr heap); 

[DllImport("kernel32.dll")] 
internal static extern uint HeapCompact(IntPtr heap, uint flags); 

[DllImport("kernel32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
internal static extern bool HeapUnlock(IntPtr heap); 
+0

¡Guau, respuesta increíble! Estaba buscando exactamente esto; ¡Gracias! –

2

Para limpiar la memoria no utilizada, use GC.Collect() ... aunque debe leer sobre por qué hacerlo y por qué es una mala idea usarla a menudo.

Si se refiere a otros recursos, deberá ser más específico.

3

Probablemente usted está buscando esta llamada de función: SetProcessWorkingSetSize

Si se ejecuta la llamada API con SetProcessWorkingSetSize -1 como un argumento, a continuación, Windows recortará el conjunto de trabajo de inmediato.

Sin embargo, si la mayor parte de la memoria todavía está siendo retenida por recursos que no ha liberado minimizando el conjunto de trabajo no hará nada. Esto combinado con la sugerencia de forzar la recolección de basura podría ser su mejor opción.

Desde la descripción de su aplicación, es posible que desee verificar también cuánta memoria está consumiendo ListView, así como los objetos de acceso a la base de datos. Tampoco tengo claro cómo estás haciendo esas llamadas a la base de datos de monitoreo. Es posible que desee aislarlo en un objeto separado y evitar tocar cualquiera de los formularios mientras se minimiza, de lo contrario, el programa se verá obligado a mantener los controles cargados y accesibles. Puede iniciar un hilo separado para la supervisión y pasar el ListView.Count como parámetro.

Algunas fuentes:

.NET Applications and the Working Set

How much memory does my .Net Application use?

Cuestiones relacionadas