【问题标题】:AS3 - Free memory (Loader, BitmapData)?AS3 - 可用内存(加载程序、BitmapData)?
【发布时间】:2012-01-05 12:51:44
【问题描述】:

由于某种原因,我的应用在运行时使用了越来越多的内存,我不知道如何转储不再需要的旧数据。

我使用加载器来加载 .png 然后我使用 BitmapData 来存储图像,这样我就可以检查每个像素并存储结果。

然后我循环这个 x 次。

当我开始第二次运行时,我不再需要旧信息,但看起来我的应用仍在存储数据(加载的图像)..

这是我的一些代码:

        public function loadImage():void{
            myLoader = new Loader();
            myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);

            if (currentFrame.toString(10).length == 1){
                currentFrameURL = txtFolder.text + "\\" + txtImageName.text + txtImageNum.text.substr(0, txtImageNum.text.length - 1) + currentFrame + txtImageType.text;
            }
            if (currentFrame.toString(10).length == 2){
                currentFrameURL = txtFolder.text + "\\" + txtImageName.text + txtImageNum.text.substr(0, txtImageNum.text.length - 2) + currentFrame + txtImageType.text;
            }
            if (currentFrame.toString(10).length == 3){
                currentFrameURL = txtFolder.text + "\\" + txtImageName.text + txtImageNum.text.substr(0, txtImageNum.text.length - 3) + currentFrame + txtImageType.text;
            }
            trace(currentFrameURL + " sent to loader...");

            myLoader.load(new URLRequest(currentFrameURL));
        }

        public function imageLoaded(event:Event):void{
            myLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, imageLoaded);

            myBitmapData = new BitmapData(parseInt(txtWidth.text),parseInt(txtHeight.text),false);
            myBitmapData.draw(event.currentTarget.content);


            //Generate preview of current image being processed..
            //myPreviewImage.source = myBitmapData;
            labelProgress.text = "Current process: " + (currentFrame + 1) + "/" + (parseInt(txtFrames.text));


            for(var y:int=0; y < parseInt(txtHeight.text) ; y++){
                for(var x:int=0; x < parseInt(txtWidth.text) ; x++){
                    currentPixelColor = myBitmapData.getPixel(x,y);
                    myTabelClass.recordPixel(currentPixelColor);
                }
            }//ett bilde ferdig scannet og lagret

            currentFrame++;

            if(currentFrame < parseInt(txtFrames.text)){
                myTabelClass.newImg(currentFrame);
                trace("sending newImg command: " + currentFrame);
                loadImage();
            }else{
                //All frames done..
                //myTabelClass.traceResult();
                Alert.show("All images scanned!\n\nClick 'OK' to add new data to XML.", "Images scanned", Alert.OK, this, insertDataToXML);
                btnSave.enabled = true;
                btnTest1.enabled = true;
            }

        }

【问题讨论】:

    标签: flash actionscript-3 apache-flex air


    【解决方案1】:

    完成myBitmapData 后,请致电myBitmapData.dispose() 和myBitmapData = null。请记住,调用dispose() 后,您的BitmapData 对象不再可用,因此您必须创建一个新实例(myBitmapData = new BitmapData())。

    顺便说一句,我没有对您的代码进行太多分析,但我注意到您使用draw() 复制了每个图像的 bitmapData,然后对其进行了处理。您可以直接使用加载的图像内容,这也可以节省内存:

    myBitmapData = Bitmap(event.target.content).bitmapData;

    如果您以后不打算使用它们,在继续下一帧之前不要忘记null每个图像。

    【讨论】:

    • 我尝试添加 myBitmapData.dispose();到最后,但这会在我下次加载图像时引发错误..
    【解决方案2】:

    不幸的是,有一个错误阻止加载程序释放内存,请参见此处:https://bugbase.adobe.com/index.cfm?event=bug&id=3071138。根据我的测试,这可能与您希望以多快的速度处理之前加载的内容有关,但这是一个猜测,不要想当然。

    其他事情:调用BitmapData.dispose() 会“立即”释放内存,但如果你不这样做,那么 BitmapData 实例仍然会被 GC 处理,但这可能需要更长的时间,并且游荡的位图可能会产生内存的印象泄漏。

    System.gc() 仅在调试器中可用,这意味着您的最终用户将无法使用它。

    在对象不再使用后设置变量,尤其是局部变量为null是没有意义的,如果编译器稍微聪明一点,它可能会将其识别为死代码并完全删除。将数据成员设置为 null 仅在您出于某种原因实际上希望它们为 null 时才有用,正如他们所说的那样,“业务逻辑原因”,不要试图“帮助”GC,你很有可能会弊大于利。当我遇到分配null 的代码时,这通常会点亮一个红色灯泡,这是一个糟糕的设计或冗余。如果您的代码很好,则不需要这样做。

    【讨论】:

    • 感谢您的帮助! =) 如果我使用较小的图像(较少的数据),我会看到我的应用程序 GC 正确,但是我的通宵实验失败了,因为它到达了全帧示例的第 97 帧。我会进一步研究它。
    • 有什么办法可以让它多线程?我有 2 个 Xeon 处理器,这给了我 16 个线程。我的应用程序仅以 100% 使用 1 个线程。这并不重要,但如果可能的话,它将使我的应用程序加速 16 倍。
    • 你有时间处理它吗? GC 调用需要时间,它们不是立即的。使用分析器。 Loader/BitmapData 对我来说很好。
    【解决方案3】:

    您处于递归状态,所以是的,您不会释放加载的预览图像。

    在再次调用loadImage()之前尝试设置myBitmapData = null。

    如果没有任何反应,您可以尝试通过在 loadImage 之前调用 System.gc() 来强制垃圾收集器:

    myBitmapData = null;
    System.gc();
    loadImage();
    

    但他们说这不是一个好习惯。 :P

    如果没有任何效果,请删除可能有帮助的递归。

    【讨论】:

    • 谢谢。我现在就试试看。移除递归是什么意思?
    • loadImage 调用imageLoaded 和imageLoaded 再次调用loadImage。您可能需要在不使用此递归的情况下重新制定逻辑。
    • 啊,我会调查一下 :) 感谢您指出 ;) 不过,我不能 100% 确定在没有递归的情况下如何做到这一点。
    • 清除位图数据以某种方式起作用。前 2 张图片加载时内存使用量没有增加,但随后开始增加.. 必须研究那个递归问题.. 知道如何解决这个问题吗? =)
    • 试试我们的好友所说的.dispose()。我忘记了=p
    【解决方案4】:

    其他答案涵盖了如何处理BitmapData,但我注意到Loaders 似乎也保留了记忆。不幸的是,除了我的经验,我无法指出任何具体的来源。您可以尝试一下,看看有什么效果:

    移动线

    myLoader = new Loader();
    

    在loadImage() 函数之外并在类构造函数中实例化该变量。这将允许您一次又一次地重复使用相同的 Loader 实例。

    【讨论】:

    • 谢谢。我试试看:)
    猜你喜欢
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多