이 발생합니다. ResourceDictionaries는 항상 인스턴스화되므로 XAML에서 리소스를 찾을 때마다 메모리에서 한 번씩 리소스 사전을 여러 번 가져올 수 있습니다. 그래서 위에서 언급 한 해결책은 아주 좋은 대안처럼 보입니다. 사실 우리의 현재 프로젝트에서이 트릭은 많이 했어요 ... 메모리 소비가 800MB에서 44MB로 크게 커졌습니다. 불행하게도이 솔루션은 비용을 부담해야합니다. 여기에 표시하고 싶습니다. SharedResourceDictionary
을 사용하는 동안이를 피할 수있는 방법을 찾으십시오.SharedResourceDictionary를 사용할 때 메모리 누수가 발생했습니다. 에 익숙한 일부 큰 wpf 응용 프로그램에서 작업 한 경우
공유 리소스 사전을 사용하여 문제를 시각화하는 작은 예제를 만들었습니다.
간단한 WPF 응용 프로그램을 만들면됩니다. 이제 UserControl을 추가 한 자원 XAML
Shared.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="myBrush" Color="Yellow"/>
</ResourceDictionary>
를 추가합니다. 숨김은 기본, 그래서 난 그냥
MyUserControl.xaml이
<UserControl x:Class="Leak.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SharedResourceDictionary="clr-namespace:Articy.SharedResourceDictionary" Height="128" Width="128">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Leak;component/Shared.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Rectangle Fill="{StaticResource myBrush}"/>
</Grid>
</UserControl>
창 코드 뒤에이
Window1.xaml.cs 같은 것을 보이는 XAML을 보여
// [ ... ]
public Window1()
{
InitializeComponent();
myTabs.ItemsSource = mItems;
}
private ObservableCollection<string> mItems = new ObservableCollection<string>();
private void OnAdd(object aSender, RoutedEventArgs aE)
{
mItems.Add("Test");
}
private void OnRemove(object aSender, RoutedEventArgs aE)
{
mItems.RemoveAt(mItems.Count - 1);
}
그리고이 창 xaml은
입니다.Window1.xaml
<Window.Resources>
<DataTemplate x:Key="myTemplate" DataType="{x:Type System:String}">
<Leak:MyUserControl/>
</DataTemplate>
</Window.Resources>
<Grid>
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="Add" Click="OnAdd"/>
<Button Content="Remove" Click="OnRemove"/>
</StackPanel>
<TabControl x:Name="myTabs" ContentTemplate="{StaticResource myTemplate}">
</TabControl>
</DockPanel>
</Grid>
</Window>
나는 프로그램이 완벽하지 알고 propably 쉽게 할 수 있지만, 문제를 보여주는 방법을 파악하는 동안이 내가 생각 해낸 것입니다. 어쨌든 :
메모리 시작과 메모리 소비량을 확인하십시오. 메모리 프로파일 러가 있으면 훨씬 쉽게됩니다. 추가 (탭을 클릭하여 표시)하고 페이지를 제거하면 모든 것이 잘 작동하는 것을 볼 수 있습니다. 아무것도 누출되지 않습니다. 이제 UserControl.Resources
섹션에서 ResourceDictionary
대신 SharedResourceDictionary
을 사용하여 Shared.xaml을 포함하십시오. 페이지를 제거한 후 MyUserControl
이 메모리에 유지되고 그 안에 MyUserControl
이 있음을 알 수 있습니다.
XAML을 통해 변환기, 사용자 컨트롤 등을 통해 인스턴스화 된 모든 작업에 이러한 문제가있는 것으로 나타났습니다. 이상하게도 사용자 지정 컨트롤에는 적용되지 않습니다. 사용자 지정 컨트롤, 데이터 템플릿 등은 실제로 인스턴스화되지 않으므로 내 추측입니다.
먼저 어떻게 피할 수 있습니까? 우리의 경우에는 SharedResourceDictionary를 사용하는 것이 필수적이지만 메모리 누수로 인해 생산적으로 사용할 수 없게됩니다. UserControls 대신 CustomControls를 사용하여 누출을 피할 수 있습니다. 이는 항상 실제적인 것은 아닙니다. 그렇다면 UserControls는 ResourceDictionary에서 강력하게 참조하는 이유는 무엇입니까? 이전에 경험 한 경험이없는 이유가 궁금합니다. 이전 질문에서 말했듯이 리소스 사전과 XAML을 절대적으로 잘못 사용하는 것처럼 보입니다. 그렇지 않으면 왜 비효율적인지 궁금합니다.
누군가가이 문제에 대해 밝힐 수 있기를 바랍니다. 사전 니코
의을 MyUserControl 인스턴스에 대한 참조를 유지하는 것을 목적이었다? –
확실히 기억할 수는 없지만, ResourceDictionary라고 생각됩니다. 내 경우에는 SharedResourceDictionary입니다. – dowhilefor