.NET最小化到托盘并最小化所需的资源

时间:2008-11-04 20:01:18

标签: c# .net vb.net visual-studio winforms

我有一个WinForms应用程序(我正在使用VB),可以最小化到系统托盘。我使用了NotifyIcon并使用Form_Resize事件在多个帖子中描述的“hackish”方法。

这一切在美学上都很好,但所使用的资源和记忆不受影响。我希望能够在最小化到系统托盘时最小化资源,就像Visual Studio一样。如果您在Visual Studio中编码,内存使用量可能会上升(取决于项目大小)超过500 MB,但是当将Visual Studio最小化到任务栏时,内存会大幅减少到(我假设的)是最小量。

有没有人知道如何做到这一点?

以下是应用程序的简短描述,如果有人发现它相关:我有一个带有ListView的窗体,其中包含我的IT部门的工作订单。该应用程序有一个“监听器”,通知何时提交新的工作订单。因此,当应用程序在系统托盘中运行时,我真正做的就是每隔几分钟将ListView中的项目数与SQL表中的行数进行比较。

编辑:更具体地说,窗体本质上具有通过控件使用的线程和资源,当窗体不可见时(在系统托盘中)这些资源仍在使用中。我可以做些什么来最小化这些资源,而不是杀死所有控件并在表单恢复时重绘它们。

4 个答案:

答案 0 :(得分:8)

调用MiniMizeMemory()将执行垃圾收集,修剪进程的工作大小,然后压缩进程的堆。

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

答案 1 :(得分:3)

您可能正在寻找此函数调用:SetProcessWorkingSetSize

如果执行API调用SetProcessWorkingSetSize并将-1作为参数,则Windows将立即修剪工作集。

但是,如果大部分内存仍然被资源占用,那么最小化工作集将无济于事。这与强制垃圾收集的建议相结合可能是你最好的选择。

从您的应用程序描述中,您可能还想验证ListView消耗的内存量以及数据库访问对象。我也不清楚你是如何进行监控数据库调用的。您可能希望将其隔离到单独的对象中,并避免在最小化时触摸任何表单,否则程序将被强制保持控件加载和可访问。您可以启动一个单独的线程进行监视,并将ListView.Count作为参数传递。

一些消息来源:

.NET Applications and the Working Set

How much memory does my .Net Application use?

答案 2 :(得分:2)

要清理未使用的内存,请使用GC.Collect()...虽然您应该阅读为什么要这样做以及为什么经常使用它通常是一个坏主意。

如果您指其他资源,则需要更加具体。

答案 3 :(得分:0)

虽然这是在C#中,但请查看源代码,它将解决您遇到的任何问题:

http://www.codeproject.com/KB/cs/NotifyIconExample.aspx