2008-11-04 8 views
8

J'ai une application WinForms (j'utilise VB) qui peut être réduite dans la barre d'état système. J'ai utilisé les méthodes "hackish" décrites dans plusieurs messages en utilisant un NotifyIcon et en jouant avec l'événement Form_Resize..NET Réduire au bac ET Réduire les ressources requises

Tout cela fonctionne esthétiquement, mais les ressources et la mémoire utilisées ne sont pas affectées. Je veux être en mesure de minimiser les ressources lors de la minimisation dans la barre d'état système, tout comme Visual Studio. Si vous codez dans Visual Studio, l'utilisation de la mémoire peut grimper (selon la taille du projet) à plus de 500 Mo, mais lors de la réduction de Visual Studio dans la barre des tâches, la mémoire diminue considérablement (ce que je suppose) .

Quelqu'un at-il la moindre idée de la façon d'accomplir cela?

Voici une brève description de l'application, si quelqu'un trouve cela pertinent: J'ai un formulaire Windows avec un ListView qui contient des ordres de travail pour mon département informatique. L'application a un "écouteur" qui notifie quand un nouvel ordre de travail est soumis. Ainsi, lorsque l'application est en cours d'exécution dans la barre d'état système, tout ce que je fais est de comparer le nombre d'éléments dans le ListView à un nombre de lignes dans une table SQL toutes les quelques minutes.

EDIT: Pour être plus précis, une forme de fenêtre a intrinsèquement des threads et des ressources utilisées au moyen des contrôles, quand le formulaire est invisible (dans la barre d'état système) ces ressources sont toujours utilisées. Que puis-je faire pour minimiser ces ressources, à court de tuer tous les contrôles et de les redessiner lorsque le formulaire est restauré.

+0

Vous exécutez votre application en dehors de VS, non? Cela va gonfler l'utilisation de la mémoire de votre application. – StingyJack

Répondre

8

Calling MiniMizeMemory() feront une collecte des ordures, rogner la taille de travail de processus, puis compacter le tas de processus.

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

Wow, réponse géniale! Je cherchais exactement cela; Merci! –

2

Pour nettoyer la mémoire inutilisée, utilisez GC.Collect() ... bien que vous deviez lire sur pourquoi le faire et pourquoi c'est généralement une mauvaise idée de l'utiliser souvent.

Si vous parlez d'autres ressources, vous devrez être plus précis.

3

Vous êtes probablement pour cet appel de fonction: SetProcessWorkingSetSize

Si vous exécutez l'appel API SetProcessWorkingSetSize avec -1 comme un argument, Windows va réduire le jeu de travail immédiatement. Cependant, si la plus grande partie de la mémoire est toujours détenue par des ressources que vous n'avez pas libérées, la réduction de l'ensemble de travail ne fera rien. Cela combiné avec la suggestion de forcer Garbage Collection pourrait être votre meilleur pari. À partir de la description de votre application, vous pouvez également vérifier la quantité de mémoire consommée par ListView ainsi que les objets d'accès à la base de données. Je ne sais pas non plus comment vous effectuez ces appels de base de données de surveillance. Vous pourriez vouloir isoler cela dans un objet séparé et éviter de toucher à l'un des formulaires tout en minimisant, sinon le programme sera forcé de garder les contrôles chargés et accessibles. Vous pouvez démarrer un thread séparé pour la surveillance et transmettre le ListView.Count en tant que paramètre.

Quelques sources:

.NET Applications and the Working Set

How much memory does my .Net Application use?

Questions connexes