当前位置:编程学习 > wap >>

反复打开关闭PhotoCamera,程序内存会一直增长,直到达到程序的内存限制如150M后崩溃,为何内存不会被回收??怪事

发现用PhotoCamera时(如识别二维码),反复打开关闭PhotoCamera,程序内存会一直增长,直到达到程序的内存限制如150M后程序报OutOfMemory异常。

下面简单的测试代码,每次new和dispose后,内存增长2M,为何?

vs2012+SDK8.0


        private void Button_Click(object sender, RoutedEventArgs e)
        {

            cam = new PhotoCamera();

            this.viewfinderBrush.SetSource(cam);

        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            cam.Dispose();

            //System.GC.Collect();//无效果
        } --------------------编程问答-------------------- System.GC.Collect()多来几次 --------------------编程问答-------------------- 你注册PhotoCamera的事件了吗?
退出页面前记得移除所有注册的事件,不然会导致内存泄漏 --------------------编程问答--------------------  cam = new PhotoCamera();放在构造函数比较合适,点一次就new一个不合理 --------------------编程问答--------------------
引用 3 楼 NianHui 的回复:
 cam = new PhotoCamera();放在构造函数比较合适,点一次就new一个不合理


这个建议不错!应该这样做。

--------------------编程问答-------------------- 如果还有引用计数,把GC.Collect()按烂它也不会回收。 --------------------编程问答--------------------
引用 1 楼 NianHui 的回复:
System.GC.Collect()多来几次


感谢!
这个我也试过了,没效果,见下面按钮事件的和Dispose在一块的://System.GC.Collect();//无效果
内存还是会每次约2M的向上涨。 --------------------编程问答--------------------
引用 2 楼 NianHui 的回复:
你注册PhotoCamera的事件了吗?
退出页面前记得移除所有注册的事件,不然会导致内存泄漏



没注册任何事件,我上面这个测试代码就是纯粹为了最少的代码测试它的内存增长情况,
先new一个,再dispose一个,同时获取ApplicationPeakMemoryUsage,发现它会一直涨。
--------------------编程问答--------------------
引用 4 楼 91program 的回复:
Quote: 引用 3 楼 NianHui 的回复:

 cam = new PhotoCamera();放在构造函数比较合适,点一次就new一个不合理


这个建议不错!应该这样做。



谢谢各位老大的热情回复!
我放在按钮里只是为了方便反复测试内存增长情况。
这个太怪了,GC也不会回收它,直到最后150M极限达到。。。

难道是因为cam定义在MainPage主页面里,就不会被回收?

不过我在其它非主页面里也定义过cam,其它页面的析构函数也会被GC执行到,但ApplicationPeakMemoryUsage还是会一直涨。。。

真是纳闷了。各位老大帮忙测测看?谢谢


namespace camWp8
{
    public partial class MainPage : PhoneApplicationPage
    {
        private PhotoCamera cam;

        
        // 构造函数
        public MainPage()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            cam = new PhotoCamera();

            this.viewfinderBrush2.SetSource(cam);

            //this.NavigationService.Navigate(new Uri("/camWp8;component/testCam.xaml", UriKind.Relative));
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            
            
            cam.Dispose();

            string total = "DeviceTotalMemory"; //设备的总内存
            string current = "ApplicationCurrentMemoryUsage";
            string peak = "ApplicationPeakMemoryUsage";
            string limit = "ApplicationWorkingSetLimit";


            var value_total = DeviceExtendedProperties.GetValue(total);
            var value_current = DeviceExtendedProperties.GetValue(current);
            var value_peak = DeviceExtendedProperties.GetValue(peak);
            var value_limit = DeviceExtendedProperties.GetValue(limit);


            MessageBox.Show(
                "total=" + (((long)value_total) / 1024 / 1024).ToString()
                + "\ncurrent=" + (((long)value_current) / 1024 / 1024).ToString()
                + "\npeak=" + (((long)value_peak) / 1024 / 1024).ToString()
                + "\nlimit=" + (((long)value_limit) / 1024 / 1024).ToString()
                );
        }

        
    }
}
--------------------编程问答-------------------- 不回收是因为还存在引用,如5楼所述。 --------------------编程问答--------------------
引用 5 楼 cuit 的回复:
如果还有引用计数,把GC.Collect()按烂它也不会回收。



版主帮忙看看下面这个写法对吗?把PhotoCamera 对象放到第二个页面了,打开页面时显示拍照内容,按手机的回退键返回上个页面,按道理这里构造和析构都是配对的,上一个页面强行调用GC.Collect(),但内存还是涨,,,怪

namespace camWp8
{
    public partial class testCam : PhoneApplicationPage
    {
        private PhotoCamera cam;

        public testCam()
        {
            InitializeComponent();

            cam = new PhotoCamera();

        }

        private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
        {
         
            cam.Dispose();

        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {

                Debug.WriteLine("cam.Init");

                viewfinderBrush.SetSource(cam);

            }
            catch (Exception ex)
            {

            }
        }

    }
} --------------------编程问答--------------------
引用 9 楼 NianHui 的回复:
不回收是因为还存在引用,如5楼所述。


版主帮忙看看下面这个写法对吗?把PhotoCamera 对象放到第二个页面了,打开页面时显示拍照内容,按手机的回退键返回上个页面,按道理这里构造和析构都是配对的,上一个页面强行调用GC.Collect(),但内存还是涨,,,怪

namespace camWp8
{
    public partial class testCam : PhoneApplicationPage
    {
        private PhotoCamera cam;

        public testCam()
        {
            InitializeComponent();

            cam = new PhotoCamera();

        }

        private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
        {
         
            cam.Dispose();

        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {

                Debug.WriteLine("cam.Init");

                viewfinderBrush.SetSource(cam);

            }
            catch (Exception ex)
            {

            }
        }

    }
}  --------------------编程问答--------------------  private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
         {
          
             cam.Dispose();
cam=null;
         } --------------------编程问答--------------------
引用 12 楼 NianHui 的回复:
 private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
         {
          
             cam.Dispose();
cam=null;
         }


这个cam=null也试过,没有效果。。。
--------------------编程问答--------------------
引用 13 楼 luxm1218 的回复:
Quote: 引用 12 楼 NianHui 的回复:

 private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
         {
          
             cam.Dispose();
cam=null;
         }


这个cam=null也试过,没有效果。。。



//viewfinderBrush.SetSource(cam); 这句注释掉,内存不会涨,但也看不到视频内容了。。
--------------------编程问答--------------------
引用 13 楼 luxm1218 的回复:
Quote: 引用 12 楼 NianHui 的回复:

 private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
         {
          
             cam.Dispose();
cam=null;
         }


这个cam=null也试过,没有效果。。。

一点也不降??
我试了下,返回到主页就降几个M,但是不会全部降下去。 --------------------编程问答--------------------
引用 15 楼 NianHui 的回复:
Quote: 引用 13 楼 luxm1218 的回复:

Quote: 引用 12 楼 NianHui 的回复:

 private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
         {
          
             cam.Dispose();
cam=null;
         }


这个cam=null也试过,没有效果。。。

一点也不降??
我试了下,返回到主页就降几个M,但是不会全部降下去。


你的可以降低并保持在一个较低的水平?

我测试的数据:
            string total = "DeviceTotalMemory"; 
            string current = "ApplicationCurrentMemoryUsage";
            string peak = "ApplicationPeakMemoryUsage";
            string limit = "ApplicationWorkingSetLimit";
上面对应的值分别是

第一次,395,10,11,150;
第二次,395,13,19,150;
第三次,395,15,21,150;
第三次,395,17,23,150;

...重复若干次后
            395,34,39,150;PeakMemory和CurrentMemory涨到了39和34.。。





--------------------编程问答-------------------- 没人遇到过这个问题?。。。 --------------------编程问答-------------------- --------------------编程问答--------------------
引用 16 楼 luxm1218 的回复:
 第一次,395,10,11,150;
第二次,395,13,19,150;
第三次,395,15,21,150;
第三次,395,17,23,150;

 ...重复若干次后
            395,34,39,150;PeakMemory和CurrentMemory涨到了39和34.。。

PeakMemory无所谓,
CurrentMemory我测试的和你结果一样,一直涨,涨5m释放3m的方式增长。

还没找到解决方案 --------------------编程问答--------------------  this.viewfinderBrush.SetSource(cam);

你这还一直引用着,可能被回收吗? --------------------编程问答--------------------
引用 20 楼 cuit 的回复:
 this.viewfinderBrush.SetSource(cam);

你这还一直引用着,可能被回收吗?


谢谢。应该就是这个引起的,但那这个如何释放呢?
这个含有viewfinderBrush和cam的相机测试页面都返回了,GC也强制Collect了,这个viewfinderBrush还存在?
官方的那个【如何为 Windows Phone 创建基本相机应用】也没提这个viewfinderBrush释放的事。。
--------------------编程问答--------------------
引用 19 楼 NianHui 的回复:
Quote: 引用 16 楼 luxm1218 的回复:


 第一次,395,10,11,150;
第二次,395,13,19,150;
第三次,395,15,21,150;
第三次,395,17,23,150;

 ...重复若干次后
            395,34,39,150;PeakMemory和CurrentMemory涨到了39和34.。。

PeakMemory无所谓,
CurrentMemory我测试的和你结果一样,一直涨,涨5m释放3m的方式增长。

还没找到解决方案


找到知音了。。。

PeakMemory很有关系,你一直重复,当它涨到ApplicationWorkingSetLimit这个值时(低内存机默认是150M),程序就挂了。。。
--------------------编程问答--------------------
引用 21 楼 luxm1218 的回复:
Quote: 引用 20 楼 cuit 的回复:

 this.viewfinderBrush.SetSource(cam);

你这还一直引用着,可能被回收吗?


谢谢。应该就是这个引起的,但那这个如何释放呢?
这个含有viewfinderBrush和cam的相机测试页面都返回了,GC也强制Collect了,这个viewfinderBrush还存在?
官方的那个【如何为 Windows Phone 创建基本相机应用】也没提这个viewfinderBrush释放的事。。


难道viewfinderBrush不释放是页面布局的问题?各位版主看看。。。


<phone:PhoneApplicationPage
    x:Class="camWp8.testCam"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d"
    shell:SystemTray.IsVisible="False" Unloaded="PhoneApplicationPage_Unloaded" Loaded="PhoneApplicationPage_Loaded">

    <!--LayoutRoot 是包含所有页面内容的根网格-->
    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid >
        <Grid.Background>
            <VideoBrush x:Name="viewfinderBrush" >
            </VideoBrush>
        </Grid.Background>


        <!--Used for debugging >-->
    </Grid>

</phone:PhoneApplicationPage> --------------------编程问答-------------------- viewfinderBrush这个对象有没有在引用?这个可能要全局静态化(public static),否则可能真会有问题。 --------------------编程问答--------------------
引用 24 楼 BEYONDMA 的回复:
viewfinderBrush这个对象有没有在引用?这个可能要全局静态化(public static),否则可能真会有问题。


谢谢。viewfinderBrush没其他引用了,就是显示下相机内容。请教下这个【全局静态化】怎么个弄法?

    public partial class testCam : PhoneApplicationPage
    {
        public static  PhotoCamera cam;

是这样么?测了没效果。。。
--------------------编程问答-------------------- --------------------编程问答-------------------- 页面启用了缓存了吗? --------------------编程问答--------------------
引用 27 楼 cuit 的回复:
页面启用了缓存了吗?


页面默认建立的,没有缓存。NavigationCacheMode这个好像是只读的也改不了。 --------------------编程问答-------------------- --------------------编程问答-------------------- --------------------编程问答--------------------  protected override void OnNavigatedFrom(NavigationEventArgs e)
        {

     
            if (e.NavigationMode == NavigationMode.Back)
            {
                PhotoCamera pc = new PhotoCamera();
                pc.Dispose();
            }
            base.OnNavigatedFrom(e);
        } --------------------编程问答-------------------- 试试吧,
主要是你的PhotoCamera其他代码应该是有引用的地方,或者你的页面其他对象还有其他地方引用,没有自动释放。

引用 楼主 luxm1218 的回复:
发现用PhotoCamera时(如识别二维码),反复打开关闭PhotoCamera,程序内存会一直增长,直到达到程序的内存限制如150M后程序报OutOfMemory异常。

下面简单的测试代码,每次new和dispose后,内存增长2M,为何?

vs2012+SDK8.0


        private void Button_Click(object sender, RoutedEventArgs e)
        {

            cam = new PhotoCamera();

            this.viewfinderBrush.SetSource(cam);

        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            cam.Dispose();

            //System.GC.Collect();//无效果
        }


this.viewfinderBrush.SetSource(cam); 

清除引用后

cam.Dispose();

--------------------编程问答-------------------- 应该还是有cam的引用吧,如果没有了,那可以试试用一个静态的cam对象,不要每次都new了。 --------------------编程问答--------------------
引用 32 楼 FreeSarge 的回复:
试试吧,
主要是你的PhotoCamera其他代码应该是有引用的地方,或者你的页面其他对象还有其他地方引用,没有自动释放。

Quote: 引用 楼主 luxm1218 的回复:

发现用PhotoCamera时(如识别二维码),反复打开关闭PhotoCamera,程序内存会一直增长,直到达到程序的内存限制如150M后程序报OutOfMemory异常。

下面简单的测试代码,每次new和dispose后,内存增长2M,为何?

vs2012+SDK8.0


        private void Button_Click(object sender, RoutedEventArgs e)
        {

            cam = new PhotoCamera();

            this.viewfinderBrush.SetSource(cam);

        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            cam.Dispose();

            //System.GC.Collect();//无效果
        }


this.viewfinderBrush.SetSource(cam); 

清除引用后

cam.Dispose();



谢谢。this.viewfinderBrush.SetSource(cam);  这个如何清除引用呢?SetSource(null)?


--------------------编程问答-------------------- cam返回的是一个流,把viewfinderBrush=null即可,然后把cam置空,dispose掉就可以了 --------------------编程问答-------------------- Dispose了没? --------------------编程问答-------------------- 遇到了相同的问题,this.viewfinderBrush.SetSource(cam);让这个页面无法析构,楼主解决了么? --------------------编程问答--------------------
引用 35 楼 coaxhappy 的回复:
cam返回的是一个流,把viewfinderBrush=null即可,然后把cam置空,dispose掉就可以了


cam置空就不能dispose了 --------------------编程问答--------------------
引用 37 楼 aidyliuliu 的回复:
遇到了相同的问题,this.viewfinderBrush.SetSource(cam);让这个页面无法析构,楼主解决了么?


最近机器重装,有一阵没研究这个了。。。
补充:移动开发 ,  Windows Phone
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,