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

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

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

有人知道如何实现吗?

以下是应用程序的简短描述,如果有人觉得相关的话:我有一个Windows表单,其中包含我们IT部门的工单,该应用程序具有一个“监听器”,通知何时提交了新的工单。因此,当应用程序在系统托盘中运行时,我只需要每隔几分钟比较ListView中的项目数与SQL表中的行数即可。

编辑:更加具体地说,窗体固有线程和通过控件使用的资源,当窗体不可见(在系统托盘中)时,这些资源仍在被使用。除了杀死所有控件并在恢复窗体时重新绘制它们之外,我该怎么做才能最小化这些资源呢?


你是在 VS 之外运行应用程序,对吧?这会增加你的应用程序的内存使用量。 - StingyJack
4个回答

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

3
您可能正在寻找这个函数调用:SetProcessWorkingSetSize 如果您将API调用SetProcessWorkingSetSize的参数设置为-1,则Windows会立即修剪工作集。
然而,如果大部分内存仍然被您未释放的资源占用,那么最小化工作集将不起作用。结合强制垃圾回收的建议可能是您最好的选择。
从您的应用程序描述中可以看出,您可能还想验证ListView和数据库访问对象消耗了多少内存。我也不清楚您如何进行监视数据库调用。您可能需要将其隔离到单独的对象中,并避免在最小化时触摸任何表单,否则程序将被迫保持控件已加载且可访问。您可以启动一个单独的线程进行监视,并将ListView.Count作为参数传递。
一些参考资料: .NET应用程序和工作集 我的.Net应用程序使用了多少内存?

2

要清理未使用的内存,请使用GC.Collect()... 但是您应该了解为什么要这样做,以及为什么经常使用它通常不是一个好主意。

如果您指的是其他资源,则需要更具体地说明。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接