在Windows Phone 8的的BitmapImage /图像控制的内存占用 [英] Memory consumption of BitmapImage/Image control in Windows Phone 8

查看:263
本文介绍了在Windows Phone 8的的BitmapImage /图像控制的内存占用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我测试WP8的应用程序,它的图像查看器显示多幅图像,我发现应用程序的内存消耗是提高并想找出如何解决它。

I am testing a WP8 app and it's image viewer to show many images, I found app's memory consumption is raising and want to find out how to solve it.

我读过从网上一些文章,但这些文章所提供的解决方案是不是在我的应用程序的工作,请阅读下面的历史。

I've read some articles from web, however the solutions provided by those articles are not working on my app, please read the history below.

首先,我找到了一篇文章的为Windows Phone 7 图像提示,它的工作是 1图片

First, I found the article "Image Tips for Windows Phone 7" and download its sample to do clean image cache testing, it's working with 1 image.

然后用于测试目的,我做这个程序是 15脱机映像里面的应用程序,编译并设置为内容,请从以下网站下载测试程序<一个href=\"https://skydrive.live.com/embed?cid=866FAAAC43FA6E14&resid=866FAAAC43FA6E14!331&authkey=AATXGEuZv2LVer8\">here.

And then for testing purposes, I make this app compiled with 15 offline images inside the app, and set as "Content", please download test app from 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.18MB)=>清除( 17.03MB )...等
和内存不会被释放,即使离开缓存页面,再去缓存页面。
这似乎文章图像的解为Windows Phone 7 提示正在为仅 1图片

When I'm testing my app, the memory is raising, like 16.02MB => Show(19.32MB) => Clear(16.15MB) => Show(20.18MB) => Clear (17.03MB)...etc And memory won't be freed even leaving caching page and go to caching page again. It seems the solution of article "Image Tips for Windows Phone 7" is working for only 1 image.

下面谈到的解决方案通过的为Windows Phone 7 图像提示。

Here comes the xaml and code-behind of solution by "Image Tips for Windows Phone 7".

[Caching.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]

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

我也试图寻找其他的解决方案,一些测试结果如下。

I also tried to search any other solutions, some testing results are as below.

(1)条<一个href=\"http://blogs.developpeur.org/kookiz/archive/2013/02/17/wpdev-memory-leak-with-bitmapimage.aspx\">[wpdev]内存泄漏与BitmapImage的:它提供了2解决方案,一种是DisposeImage API,另一种是设置BitmapImage的来源如下空。另外,文章让我们知道,我们必须小心事件处理程序附加/ dettach,但是我的测试应用程序不会在缓存网页事件处理程序。

(1) Article "[wpdev] Memory leak with BitmapImage": It provides 2 solutions, one is DisposeImage API, another is to set BitmapImage source to null as below. Also the article let us know we must be careful about event handler attach/dettach, however my testing app doesn't have event handler in caching page.

[DisposeImage]

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

[设置为null]

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

(2)条<一个href=\"http://stackoverflow.com/questions/13816569/windows-phone-listbox-with-images-out-of-memory\">Windows电话:列表框与图像外的内存:它提供了一个APIDisposeImage比(1)的下面,但是这也不能正常工作,我还是得到了提高内存症状差别不大

(2) Article "Windows phone: listbox with images out-of-memory": It provides an API "DisposeImage" with little difference than (1)'s as below, but this also doesn't work, I still got the memory raising symptom.

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
    {}
}

(三)项<一个href=\"http://stackoverflow.com/questions/13355496/cannot-find-the-memory-leak/13482619#13482619\">Cannot找到内存泄漏:它提供了相同的解决方案2如上所述,它也提到的问题不能瑞普的独立存储的图像,但我的测试应用程序的图片均来自独立存储

(3) Article "Cannot find the memory leak": It provides the same 2 solutions as above mentioned, also it mentioned the issue cannot repro for isolated storage's images, however my testing app's images are from isolated storage.

(4)我也试过1000的图像,测试结果是应用程序崩溃时,应用程序显示周围190图像顺序,请参阅Windows Phone应用程序分析图形下面的内存。

(4) I also tried for 1000 images, the testing result is app crash when the app showed around 190 images sequentially, please refer to the Windows Phone Application Analysis Graphics for memory below.

最后,感谢您的耐心阅读,我的问题和历史,我一直工作在此找到了很多天的解决方案。
如果您有任何线索或解决方案,请您让我知道。

Finally, thanks for your patience to read my question and history, I've been working on this to find solution for many days. If you have any clue or solution, please kindly let me know.

感谢。

推荐答案

我同样的问题打交道,我想,到最后,那其实我已经找到一个解决办法,我不是一个亲程序员,但这里是我的解决方案:

I was dealing with the same problem and I think, in the end, that actually I've found a workaround, I am not a pro programmer but here is my solution:

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

希望这有助于:)

Hope this help :)

这篇关于在Windows Phone 8的的BitmapImage /图像控制的内存占用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆