Gerir o uso de memória em aplicações de ambiente de trabalho do SDK de Aplicações Windows

Uma gestão eficiente da memória ajuda a sua aplicação a funcionar bem, especialmente em dispositivos com recursos limitados. Este artigo descreve estratégias para gerir a memória numa aplicação desktop do SDK de Aplicações Windows, especialmente quando a janela da sua aplicação não é visível.

Importante

As aplicações de ambiente de trabalho não são automaticamente suspensas pelo sistema. Continuam a consumir memória enquanto correm. A gestão proativa da memória melhora a resposta geral do sistema e a duração da bateria.

Monitorar o uso de memória

Usa o Windows. Classe System.MemoryManager para verificar o consumo de memória da sua aplicação e o estado da memória em todo o sistema:

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

Também pode subscrever MemoryManager.AppMemoryUsageLimitChanging e MemoryManager.AppMemoryUsageIncreased para reagir à pressão de memória.

Reduzir a memória quando a janela está oculta

Embora o sistema não suspenda a sua aplicação de desktop, pode reduzir o consumo de memória quando a sua janela está minimizada ou oculta. Isto torna mais recursos disponíveis para a aplicação em primeiro plano e prolonga a duração da bateria.

Detetar quando a janela está escondida

Microsoft.UI.Xaml.Window não expõe um evento VisibilityChanged. Em vez disso, use o Window.Activated evento para detetar quando a sua janela perde o foco, ou use AppWindow.Changed para detetar quando está minimizada:

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

O que lançar

Quando a sua janela estiver oculta, considere libertar:

  • Imagens e bitmaps em cache — Eliminar bitmaps grandes que são necessários apenas para exibição.
  • Recursos de destino de renderização — Liberta recursos da GPU usados para renderização.
  • Visualizar dados do modelo — Limpar coleções ou dados em cache que podem ser recarregados quando o utilizador regressar.
  • Histórico de navegação — Se a sua aplicação tiver uma pilha de navegação, limpe as páginas em cache.
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
}

Pressão de memória do sistema de controlo

Registe-se no evento MemoryManager.AppMemoryUsageIncreased para detetar quando a pressão de memória do sistema aumenta:

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

Embora as aplicações de ambiente de trabalho não sejam automaticamente terminadas pelo sistema para libertar memória (ao contrário do UWP), reduzir o consumo de memória quando o sistema está sob pressão de memória mantém o sistema reativo e evita potenciais situações de memória insuficiente.

Melhores práticas

  • Liberta o que conseguires recarregar. Liberta apenas recursos que possas reconstruir mais tarde a partir de disco, rede ou computação.
  • Reduza gradualmente. Comece por libertar primeiro os maiores itens (imagens, caches, recolhas de dados).
  • Teste em dispositivos com pouca memória. Verifica se a tua gestão de memória funciona em dispositivos com 4 GB ou menos de RAM.
  • Evite segurar objetos grandes em campos estáticos. Usa padrões de carregamento preguiçosos em vez disso.