高效的内存管理可帮助应用运行良好,尤其是在资源有限的设备上。 本文介绍在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.AppMemoryUsageLimitChanging 和 MemoryManager.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 的设备上运行。
- 避免在静态字段中保存大型对象。 请改用延迟加载模式。