Back to Skills

optimizing-wpf-memory

verified

Covers WPF memory optimization including Freezable patterns, common memory leak causes, and diagnostic techniques. Use when experiencing memory growth, implementing resource caching, or debugging memory issues.

View on GitHub

Marketplace

dotnet-claude-plugins

christian289/dotnet-with-claudecode

Plugin

wpf-dev-pack

development

Repository

christian289/dotnet-with-claudecode
5stars

wpf-dev-pack/skills/optimizing-wpf-memory/SKILL.md

Last Verified

January 23, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/christian289/dotnet-with-claudecode/blob/main/wpf-dev-pack/skills/optimizing-wpf-memory/SKILL.md -a claude-code --skill optimizing-wpf-memory

Installation paths:

Claude
.claude/skills/optimizing-wpf-memory/
Powered by add-skill CLI

Instructions

# WPF Memory Optimization

## 1. Freezable Pattern

### Why Freeze?

| Benefit | Description |
|---------|-------------|
| Thread-safe | Can be used across threads |
| No change tracking | Reduces overhead |
| Renderer optimization | Better GPU utilization |

### Basic Usage
```csharp
// Always freeze static resources
var brush = new SolidColorBrush(Colors.Red);
brush.Freeze();

var pen = new Pen(Brushes.Black, 1);
pen.Freeze();
```

### XAML Freeze
```xml
<Window xmlns:po="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
        mc:Ignorable="po">
    <Window.Resources>
        <SolidColorBrush x:Key="FrozenBrush" Color="Red" po:Freeze="True"/>
    </Window.Resources>
</Window>
```

### When Freeze Fails
```csharp
if (brush.CanFreeze)
    brush.Freeze();
else
    // Has bindings or animations - cannot freeze
```

### Modifying Frozen Objects
```csharp
var clone = frozenBrush.Clone(); // Creates unfrozen copy
clone.Color = Colors.Blue;
clone.Freeze(); // Freeze again if needed
```

## 2. Common Memory Leaks

### Event Handler Leaks
```csharp
// ❌ LEAK: Static event holds reference
SomeStaticClass.StaticEvent += OnEvent;

// ✅ FIX: Unsubscribe in Unloaded
Unloaded += (s, e) => SomeStaticClass.StaticEvent -= OnEvent;
```

### CompositionTarget.Rendering Leak
```csharp
// ❌ LEAK: Never unsubscribed
CompositionTarget.Rendering += OnRendering;

// ✅ FIX: Always unsubscribe
Loaded += (s, e) => CompositionTarget.Rendering += OnRendering;
Unloaded += (s, e) => CompositionTarget.Rendering -= OnRendering;
```

### Binding Without INotifyPropertyChanged
```csharp
// ❌ LEAK: PropertyDescriptor retained
public string Name { get; set; } // No INPC

// ✅ FIX: Implement INPC
public string Name
{
    get => _name;
    set { _name = value; OnPropertyChanged(); }
}
```

### DispatcherTimer Leak
```csharp
// ❌ LEAK: Timer keeps running
_timer = new DispatcherTimer();
_timer.Tick += OnTick;
_timer.Start();

// ✅ FIX: Stop and cleanup
Unloaded += (s, e) =>
{
    _timer.

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
3473 chars