有效的記憶體管理有助於你的應用程式表現良好,尤其是在資源有限的裝置上。 本文說明了在 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.AppMemoryUsageIncrease ,以回應記憶體壓力。
當視窗被隱藏時,減少記憶體
雖然系統不會暫停桌面應用程式,但當視窗最小化或隱藏時,你可以減少記憶體消耗。 這讓前景應用程式能使用更多資源,並延長電池續航力。
偵測視窗是否隱藏
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 的裝置上正常運作。
- 避免將大型物體置於靜態場中。 改用延遲載入模式。