管理Windows 应用 SDK桌面应用中的内存使用情况

高效的内存管理可帮助应用运行良好,尤其是在资源有限的设备上。 本文介绍在Windows 应用 SDK桌面应用中管理内存的策略,尤其是在应用窗口不可见时。

Important

桌面应用不会被系统自动挂起。 它们继续在运行时消耗内存。 主动内存管理可提高系统的整体响应能力和电池使用时间。

监视内存使用量

使用Windows。System.MemoryManager 类用于检查应用的内存消耗和系统范围的内存状态:

ulong appMemoryUsage = Windows.System.MemoryManager.AppMemoryUsage;
ulong appMemoryLimit = Windows.System.MemoryManager.AppMemoryUsageLimit;
Windows.System.AppMemoryUsageLevel level = Windows.System.MemoryManager.AppMemoryUsageLevel;

System.Diagnostics.Debug.WriteLine(
    $"Memory: {appMemoryUsage / 1024 / 1024} MB used, " +
    $"limit: {appMemoryLimit / 1024 / 1024} MB, level: {level}");

还可以订阅 MemoryManager.AppMemoryUsageLimitChangingMemoryManager.AppMemoryUsageIncreased 以响应内存压力。

隐藏窗口时减少内存

尽管系统不会暂停桌面应用,但当窗口最小化或隐藏时,可以降低内存消耗。 这使得更多的资源可用于前台应用并延长电池使用时间。

检测窗口何时被隐藏

Microsoft.UI.Xaml.Window 不公开 VisibilityChanged 事件。 请改用 Window.Activated 事件来检测窗口何时失去焦点,或者使用 AppWindow.Changed 来检测窗口何时最小化:

var m_window = App_Window;

void ReduceMemoryUsage() { }
void RestoreResources() { }

m_window.Activated += (sender, args) =>
{
    if (args.WindowActivationState == WindowActivationState.Deactivated)
    {
        // Window lost focus — consider reducing memory usage
        ReduceMemoryUsage();
    }
    else
    {
        // Window is active — reload resources
        RestoreResources();
    }
};

// To specifically detect minimize, use AppWindow.Changed
var appWindow = m_window.AppWindow;
appWindow.Changed += (sender, args) =>
{
    if (args.DidPresenterChange &&
        sender.Presenter is OverlappedPresenter presenter &&
        presenter.State == OverlappedPresenterState.Minimized)
    {
        // Window is minimized — reduce memory usage
        ReduceMemoryUsage();
    }
};

要发布的内容

当窗口处于隐藏状态时,请考虑释放:

  • 缓存的图像和位图 — 释放仅用于显示的大型位图。
  • 呈现目标资源 - 释放用于呈现的 GPU 资源。
  • 视图模型数据 - 清除集合或缓存的数据,当用户返回时可以重新加载。
  • 导航历史记录 - 如果应用具有导航堆栈,请清除缓存的页面。
private System.Collections.Generic.List<object>? _imageCache;
private global::Microsoft.UI.Xaml.Window m_window = App_Window;

private void ReduceMemoryUsage()
{
    // Release cached images
    _imageCache?.Clear();

    // Clear navigation cache
    if (m_window.Content is Frame rootFrame)
    {
        rootFrame.CacheSize = 0;
    }

    // Hint the GC to collect if appropriate, without forcing a blocking collection.
    // Only call this in response to system memory pressure, not on every hide.
    GC.Collect(2, GCCollectionMode.Optimized, blocking: false);
}

private void RestoreResources()
{
    // Restore navigation cache
    if (m_window.Content is Frame rootFrame)
    {
        rootFrame.CacheSize = 10;
    }

    // Reload other resources as needed
}

应对系统内存压力

注册 MemoryManager.AppMemoryUsageIncreased 事件,以检测系统内存压力何时增加:

void ReduceMemoryUsage() { }

Windows.System.MemoryManager.AppMemoryUsageIncreased += (sender, e) =>
{
    var level = Windows.System.MemoryManager.AppMemoryUsageLevel;

    if (level == Windows.System.AppMemoryUsageLevel.OverLimit ||
        level == Windows.System.AppMemoryUsageLevel.High)
    {
        ReduceMemoryUsage();
    }
};

Tip

即使系统不会自动终止桌面应用以释放内存(与 UWP 不同),在内存压力期间减少占用空间,使系统保持响应并避免潜在的内存不足情况。

最佳做法

  • 发布可重新加载的内容。 仅释放那些之后还能通过磁盘、网络或重新计算来重建的资源。
  • 逐渐减少。 首先首先发布最大的项(图像、缓存、数据收集)。
  • 在低内存设备上进行测试。 验证内存管理在具有 4 GB 或更少 RAM 的设备上运行。
  • 避免在静态字段中保存大型对象。 请改用延迟加载模式。