का उपयोग करते समय मेमोरी लीक यदि आपने कुछ बड़े wpf अनुप्रयोगों पर काम किया है तो आप this से परिचित हो सकते हैं। चूंकि संसाधन शब्दकोश हमेशा तत्काल होते हैं, हर बार जब वे XAML में पाए जाते हैं तो हम स्मृति में एक संसाधन शब्दकोश को कई बार समाप्त कर सकते हैं। तो उपर्युक्त समाधान एक बहुत अच्छा विकल्प की तरह लगता है। असल में हमारे वर्तमान प्रोजेक्ट के लिए इस चाल ने बहुत कुछ किया ... 800 एमबी से 44 एमबी तक मेमोरी खपत, जो वास्तव में एक बड़ा प्रभाव है। दुर्भाग्यवश यह समाधान एक लागत पर आता है, जिसे मैं यहां दिखाना चाहता हूं, और उम्मीद है कि SharedResourceDictionary
का उपयोग करते समय इसे टालने का एक तरीका ढूंढें।ShareResourceDictionary
मैंने साझा संसाधन शब्दकोश के साथ समस्या को देखने के लिए एक छोटा सा उदाहरण बनाया।
बस एक साधारण WPF एप्लिकेशन बनाएं। एक संसाधन 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>
जोड़ें एक UserControl जोड़ें। codebehind बस डिफ़ॉल्ट है, इसलिए मैं सिर्फ XAML
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 तरह दिखता दिखाने
// [ ... ]
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 इस
0 की तरह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
के बजाय ResourceDictionary
के बजाय का उपयोग साझा.एक्सएमएल शामिल करने के लिए करें। आप देखेंगे कि MyUserControl
किसी पृष्ठ को हटाने के बाद स्मृति में रखा जाएगा, और इसमें MyUserControl
होगा।
मुझे लगा कि XAML के माध्यम से कन्वर्टर्स, उपयोगकर्ता नियंत्रण इत्यादि के माध्यम से तत्काल यह सब कुछ होता है। आश्चर्यजनक रूप से यह कस्टम नियंत्रणों के साथ नहीं होगा। मेरा अनुमान है, क्योंकि कस्टम नियंत्रण, डेटा टेम्पलेट्स आदि पर कुछ भी वास्तव में तत्काल नहीं है।
तो पहले हम इससे कैसे बच सकते हैं? SharedResourceDictionary का उपयोग कर हमारे मामले में एक जरूरी है, लेकिन मेमोरी लीक इसे उत्पादक रूप से उपयोग करना असंभव बनाता है। लीक को UserControls के बजाय कस्टमकंट्रोल का उपयोग करके टाला जा सकता है, जो हमेशा व्यावहारिक रूप से नहीं होता है। तो UserControls को संसाधन संसाधन द्वारा संदर्भित क्यों मजबूत किया जाता है? मुझे आश्चर्य है कि किसी ने पहले ऐसा क्यों अनुभव नहीं किया, जैसा कि मैंने पुराने प्रश्न में कहा था, ऐसा लगता है कि हम संसाधन शब्दकोशों और एक्सएएमएल का बिल्कुल गलत इस्तेमाल करते हैं, अन्यथा मुझे आश्चर्य है कि वे इतने अक्षम क्यों हैं।
मुझे उम्मीद है कि कोई इस मामले पर कुछ प्रकाश डाल सकता है।
अग्रिम निको
अपनी स्मृति प्रोफाइलर में, क्या वस्तु MyUserControl उदाहरण के संदर्भ में रखते हुए किया गया था? –
मुझे निश्चित रूप से याद नहीं है, लेकिन मुझे लगभग निश्चित है कि यह एक संसाधन डिक्शनरी था, मेरे मामले में एक साझाResourceDictionary। – dowhilefor