2013-08-08 3 views
9

मैं एक WP8 ऐप का परीक्षण कर रहा हूं और यह कई छवियों को दिखाने के लिए छवि दर्शक है, मैंने पाया कि ऐप की मेमोरी खपत बढ़ रही है और इसे हल करना है।विंडोज फोन में बिटमैप छवि/छवि नियंत्रण की मेमोरी खपत 8

मैंने वेब से कुछ लेख पढ़े हैं, हालांकि उन लेखों द्वारा प्रदान किए गए समाधान मेरे ऐप पर काम नहीं कर रहे हैं, कृपया नीचे दिए गए इतिहास को पढ़ें।

सबसे पहले, मुझे लेख "Image Tips for Windows Phone 7" मिला और स्वच्छ छवि कैश परीक्षण करने के लिए इसका नमूना डाउनलोड करें, यह 1 छवि के साथ काम कर रहा है।

और फिर परीक्षण प्रयोजनों के लिए, मैं इस अनुप्रयोग 15 ऑफ़लाइन छवियों ऐप्लिकेशन के अंदर के साथ संकलित, और "सामग्री" के रूप में स्थापित करना, here से परीक्षण एप्लिकेशन डाउनलोड करें।

मेरे परीक्षण कदम हैं:

(1) Launch app 
(2) Go to Image Caching page 
(3) Enable checkbox "Avoid Image Caching" 
(4) Continuously tapping button Show/Clear 
(5) Keep watching the memory status textblock at the bottom 

जब मैं की तरह 16.02MB => शो (19.32MB) => साफ (16.15MB) मेरे ऐप, स्मृति, बढ़ा रहा है परीक्षण कर रहा हूँ => दिखाएँ (20.18 एमबी) => साफ़ करें (17.03 एमबी) ... आदि और स्मृति को कैशिंग पृष्ठ छोड़ने और फिर से कैशिंग पृष्ठ पर जाने से मुक्त नहीं किया जाएगा। ऐसा लगता है कि लेख "Image Tips for Windows Phone 7" का समाधान केवल 1 छवि के लिए काम कर रहा है।

यहां "Image Tips for Windows Phone 7" द्वारा समाधान के xaml और कोड-पीछे आता है।

[Caching.xaml]

 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> 
      <StackPanel Orientation="Horizontal" VerticalAlignment="Top"> 
       <ToggleButton Content="Show" Width="150" Checked="ShowImageClicked" Unchecked="ClearImageClicked"/> 
       <CheckBox x:Name="cbAvoidCache" Content="Avoid Image Caching"/> 
      </StackPanel> 
      <Image x:Name="img" Grid.Row="2" Width="256" Height="192"/> 
      <TextBlock x:Name="tbMemory" Grid.Row="2" Text="Memory: " VerticalAlignment="Bottom" Style="{StaticResource PhoneTextLargeStyle}"/> 
     </Grid> 

[Caching.xaml.cs]

public partial class Caching : PhoneApplicationPage 
{ 
    public Caching() 
    { 
     InitializeComponent(); 

     DispatcherTimer timer = new DispatcherTimer(); 
     timer.Interval = TimeSpan.FromMilliseconds(500); 
     timer.Start(); 
     timer.Tick += delegate 
     { 
      GC.Collect(); 
      tbMemory.Text = string.Format("Memory: {0} bytes", DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage")); 
     }; 
    } 

    private int nIndex = 1; 
    BitmapImage bitmapImageFromUri = new BitmapImage(); 
    private void ShowImageClicked(object sender, RoutedEventArgs e) 
    { 
     string strImage = string.Format("../ImagesAsContent/{0:D2}.jpg", nIndex); 
     bitmapImageFromUri.UriSource = new Uri(strImage, UriKind.Relative); 
     img.Source = bitmapImageFromUri; 

     nIndex++; 
     if (nIndex > 15) 
     { 
      nIndex = 1; 
     } 

     (sender as ToggleButton).Content = "Clear"; 
    } 

    private void ClearImageClicked(object sender, RoutedEventArgs e) 
    { 
     if (cbAvoidCache.IsChecked == true) 
     { 
      // set the UriSource to null in order to delete the image cache 
      BitmapImage bitmapImageFromUri = img.Source as BitmapImage; 
      bitmapImageFromUri.UriSource = null; 
     } 
     img.Source = null; 
     (sender as ToggleButton).Content = "Show"; 
    } 
} 

मैं भी किसी अन्य समाधान खोज करने के लिए करने की कोशिश की, कुछ परीक्षण के परिणामों के रूप में नीचे हैं।

(1) अनुच्छेद "[wpdev] Memory leak with BitmapImage": यह 2 समाधान प्रदान करता है, एक डिस्प्ले इमेज एपीआई है, दूसरा बिटमैप छवि स्रोत को नीचे के रूप में सेट करना है। साथ ही लेख हमें बताता है कि हमें इवेंट हैंडलर अटैच/डिटेच के बारे में सावधान रहना चाहिए, हालांकि मेरे परीक्षण ऐप में कैशिंग पेज में इवेंट हैंडलर नहीं है।

[DisposeImage]

private void DisposeImage(BitmapImage image) 
{ 
    if (image != null) 
    { 
     try 
     { 
      using (var ms = new MemoryStream(new byte[] { 0x0 })) 
      { 
       image.SetSource(ms); 
      } 
     } 
     catch (Exception) 
     { 
     } 
    } 
} 

[सेट अशक्त]

BitmapImage bitmapImage = image.Source as BitmapImage; 
bitmapImage.UriSource = null; 
image.Source = null; 

(2) अनुच्छेद "Windows phone: listbox with images out-of-memory": किसी API "DisposeImage" की तुलना में थोड़ा अंतर के साथ प्रदान करता है (1) नीचे जैसा है, लेकिन यह भी काम नहीं करता है, मुझे अभी भी स्मृति बढ़ाने के लक्षण मिल गए हैं।

public static void DisposeImage(BitmapImage image) 
{ 
    Uri uri= new Uri("oneXone.png", UriKind.Relative); 
    StreamResourceInfo sr=Application.GetResourceStream(uri); 
    try 
    { 
    using (Stream stream=sr.Stream) 
    { 
     image.DecodePixelWidth=1; //This is essential! 
     image.SetSource(stream); 
    } 
    } 
    catch 
    {} 
} 

(3) अनुच्छेद "Cannot find the memory leak": यह एक ही 2 समाधान के रूप में उल्लेख ऊपर, यह भी यह उल्लेख किया मुद्दा अलग भंडारण की छवियों के लिए repro नहीं कर सकते हैं प्रदान करता है, फिर भी मेरा परीक्षण एप्लिकेशन की छवियों से अलग-थलग रखने की जगह से कर रहे हैं।

(4) मैंने 1000 छवियों के लिए भी कोशिश की, परीक्षण परिणाम ऐप क्रैश है जब ऐप अनुक्रमिक रूप से लगभग 190 छवियों को दिखाता है, कृपया नीचे दी गई स्मृति के लिए विंडोज फोन एप्लिकेशन विश्लेषण ग्राफिक्स देखें। enter image description here

अंत में, मेरे प्रश्न और इतिहास को पढ़ने के लिए आपके धैर्य के लिए धन्यवाद, मैं इस पर कई दिनों तक समाधान खोजने के लिए काम कर रहा हूं। यदि आपके पास कोई सुराग या समाधान है, तो कृपया मुझे बताएं।

धन्यवाद।

+1

अच्छा सवाल, एक ही समस्या है। यहां कोई खबर है? –

+0

अभी भी एक समाधान की तलाश में है। जाहिर है, यह एक WP7.5 बग है, जिसका अर्थ है कि यह WP8 पर भी होता है अगर आप केवल WP8 को लक्षित नहीं करते हैं। –

उत्तर

3

मैं, अंत में एक ही समस्या से निपटने किया गया था और मुझे लगता है, कि वास्तव में मैं एक वैकल्पिक हल मिल गया है, मैं एक समर्थक प्रोग्रामर नहीं कर रहा हूँ, लेकिन यहाँ मेरे समाधान है:

public Task ReleaseSingleImageMemoryTask(MyImage myImage, object control) 
    { 
     Pivot myPivot = control as Pivot; 
     Task t = Task.Factory.StartNew(() => 
     { 
      Deployment.Current.Dispatcher.BeginInvoke(() => 
      { 
       if (myImage.img.UriSource != null) 
       { 
        myImage.img.UriSource = null; 
        DisposeImage(myImage.img); 
       } 
       PivotItem it = (PivotItem)(myPivot.ItemContainerGenerator.ContainerFromIndex(myImage.number % 10)); 
       Image img = FindFirstElementInVisualTree<Image>(it); 
       if (img != null) 
       { 
        img.Source = null; 
        GC.Collect(); 
       } 
      }); 
      myImage.released = true; 
     }); 
     return t; 
    } 


private T FindFirstElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject 
    { 
     var count = VisualTreeHelper.GetChildrenCount(parentElement); 
     if (count == 0) 
      return null; 

     for (int i = 0; i < count; i++) 
     { 
      var child = VisualTreeHelper.GetChild(parentElement, i); 

      if (child != null && child is T) 
      { 
       return (T)child; 
      } 
      else 
      { 
       var result = FindFirstElementInVisualTree<T>(child); 
       if (result != null) 
        return result; 
      } 
     } 
     return null; 
    } 

    private void DisposeImage(BitmapImage img) 
    { 
     if (img != null) 
     { 
      try 
      { 
       using (var ms = new MemoryStream(new byte[] { 0x0 })) 
       { 
        img = new BitmapImage(); 
        img.SetSource(ms); 
       } 
      } 
      catch (Exception e) 
      { 
       System.Diagnostics.Debug.WriteLine("ImageDispose FAILED " + e.Message); 
      } 
     } 
    } 

आशा इस मदद :)

+0

हाय डेमियन, आपकी प्रतिक्रिया के लिए धन्यवाद, हालांकि मैं अब इस मुद्दे का परीक्षण नहीं कर रहा हूं, फिर भी आपके उत्तर के लिए धन्यवाद। –

+0

कृपया मेरी मदद करें http://stackoverflow.com/questions/24161008/coverflow-with-out-of-memory – user2056563

+1

जब आप उस छवि का निपटान करने का प्रयास करते हैं जिसे आप 'img = new BitmapImage();' कहते हैं। क्या वह पूरी चीज के उद्देश्य को हराने में नहीं है? – thumbmunkeys

संबंधित मुद्दे