Как освободить память после использования FileRerence?

См. [Решение]


FileReference.load(); не имеет функции выгрузки, как и new Loader ().unload();.

Это должно быть "ОШИБКА" от Flash или FileReference требуется улучшение, введите новую версию и добавьте такую ​​функцию: FileReference.unload();

Или я ошибаюсь и существует РЕШЕНИЕ?

Я попытался установить "NULL" для переменной типа FileReference, но очевидно, что это не работает, поскольку Flash работает с GC (сборщиком мусора), но это не главная тема вопроса.

Проблема в том, что при загрузке нескольких файлов с помощью new FileReferenceList необходимо много памяти, но я не могу освободить память после процесса.

Как освободить память после использования FileRerence?

Смотрите мой код:

Main.as

package {
     import com.mainpackage.LoaderTestCase;

     import flash.net.FileReferenceList;
     import flash.net.FileReference;
     import flash.net.FileFilter;
     import flash.events.Event;
     import flash.display.MovieClip;

     public class Main extends MovieClip {
          private var listFiles:Array;
          private var allTypes:Array;
          private var fileRef:FileReferenceList;
          private var test:int;

          public function Main()
          {
               test = 0;
               listFiles     = [];
               allTypes     = [];
               fileRef          = new FileReferenceList();
               fileRef.addEventListener(Event.SELECT, select);

               fileRef.browse(allTypes);
          }

          private function select(e:Event):void
          {
               listFiles = fileRef.fileList;

               for(var i:uint=0, j:uint=listFiles.length; i<j; i++)
               {
                    insert(i);
               }
          }

          private function insert(c:int):void
          {
               var fire:LoaderTestCase = new LoaderTestCase(listFiles[c]);

               fire.destroy(function():void
               {
                    //Delete LoaderTestCase after timeout ???
                    fire = null;
                    test++;
                    if(test>=listFiles.length) {//Remove FileReference
                         fileRef.removeEventListener(Event.SELECT, select);
                         fileRef = null;

                         for(var i:uint=0, j:uint=listFiles.length; i<j; i++) {
                              listFiles[i] = null;
                         }
                         listFiles = null;

                         trace("Clear memory");
                    }
               });
          }
     }
}

LoaderTestCase.as

package com.mainpackage
{
    import flash.net.FileReference;
    import flash.events.Event;
    import flash.display.Loader;

    public class LoaderTestCase
    {
        private var file:FileReference;
        private var loader:Loader;
        private var callback:Function;

        public function LoaderTestCase(e:FileReference)
        {
            file = e;
            trace("OPEN: " + file.name);
            file.addEventListener(Event.COMPLETE, loadFile);
            file.load();
            e = null;
        }

        public function loadFile(e:Event):void
        {
            file.removeEventListener(Event.COMPLETE, loadFile);

            trace("LOAD: " + file.name);

            file    = null;
            e       = null;
            callback();
        }

        public function destroy(a:Function):void
        {
            callback = a;
        }
    }
}

person Community    schedule 29.03.2014    source источник
comment
Вы пробовали unloadAndStop(true)?   -  person Sean Fujiwara    schedule 30.03.2014
comment
@SeanFujiwara не работает   -  person Guilherme Nascimento    schedule 30.03.2014
comment
System.gc () предназначен для использования только для тестирования / отладки   -  person sanchez    schedule 30.03.2014
comment
@ san.chez Я сделал все, что вы сказали (игнорируя System.gc), но, похоже, ничего не работает.   -  person Guilherme Nascimento    schedule 30.03.2014
comment
Вы пробовали использовать слабые ссылки или вручную удалять прослушиватели событий? Пожалуйста, прочтите мой ответ внимательно   -  person sanchez    schedule 30.03.2014
comment
@ san.chez извините за мою глупость в использовании слов, это не совсем то, что я имею в виду, не знаю, как описать. Я сделал все, что вы сказали, но ничего не вышло.   -  person Guilherme Nascimento    schedule 30.03.2014


Ответы (4)


Удалите прослушиватели событий, прежде чем обнулить объект прослушивания.

Вы можете использовать слабые ссылки, чтобы разрешить удаление слушателей, когда объект собран с мусором.

object.addEventListener( ......, ......., false, 0, true );

например, в вашей функции LoadFile:

        ...
        LoadFile(file);
    }
});
...

должно быть:

        ...
        LoadFile(file);
    }
}, false, 0, true );
...

Или вам придется удалить их вручную.

Для этого вам нужно будет переместить обработчики событий в новые именованные функции.

Также вам понадобится массив для хранения ссылок на слушателей и объекты прослушивания, чтобы иметь возможность удалять слушателей ПОСЛЕ того, как слушатели больше не нужны, и ДО обнуления объекта прослушивания.

ПОЖАЛУЙСТА, ОБРАТИ ВНИМАНИЕ:

Когда вы тестируете его и наблюдаете за текущим использованием памяти, не забудьте принудительно запустить сборщик мусора, когда вы чувствуете, что использование памяти уже должно было снизиться, но этого не произошло.

GC срабатывает, когда хочет, и совсем не обязательно после того, как что-то было обнулено при выгрузке.

Чтобы быть ясным, я говорю только о принудительном использовании GC во время разработки / тестирования.

person sanchez    schedule 29.03.2014
comment
Вы пробовали заставить gc? И если да, то какая разница? - person sanchez; 30.03.2014
comment
Не следует заставлять сборщик мусора очищаться, сборщик мусора очищается автоматически ... вы должны обнулить каждую ссылку на объект, чтобы сборщик мусора знал, что вы больше не используете этот экземпляр. - person Zhafur; 30.03.2014
comment
@Zhafur, полностью согласен, но я имел в виду: заставить gc просто проверить, не был ли он уничтожен gc еще (!). - person sanchez; 30.03.2014
comment
Добавил ответ, в основном то, что вы сказали, но с примером. - person Zhafur; 30.03.2014
comment
@Zhafur Я установил null во всем, что мог, а затем использовал GC и не работал. Или забыл где-то установить? - person Guilherme Nascimento; 30.03.2014
comment
Обновляю свой ответ. Я перешел в пакеты и классы. Мне пришлось ввести немного длинный почтовый индекс, но он не работал. - person Guilherme Nascimento; 30.03.2014
comment
Простите за незнание, но разве не прав }, false, 0, true); вместо }, false, true);? Обновляю свой вопрос. - person Guilherme Nascimento; 30.03.2014
comment
Да, совершенно верно! :) priority = 0, и сделайте то же самое для прослушивателя событий test.contentLoaderInfo - person sanchez; 30.03.2014
comment
Также добавьте где-нибудь временную кнопку, чтобы вы могли щелкнуть ее, чтобы принудительно выполнить сборку мусора, чтобы проверить, помогли ли недельные ссылки (или удаление слушателей вручную). - person sanchez; 30.03.2014
comment
@ san.chez Я попробовал все ваши советы, но ничего не вышло. Проблема действительно в FileReference.load, который не освобождает память после использования, или Flash не имеет функции для выгрузки FileReference (что-то вроде FileReference.unload), другими словами, Flash нуждается в улучшении. Если вы не согласны со мной, то скажите, что делать, пожалуйста ... все перепробовал ... и ничего ... Спасибо за ваши усилия, чтобы помочь мне. - person Guilherme Nascimento; 31.03.2014
comment
@GuilhermeNascimento попробуйте удалить прослушиватель для вашего FileReferenceList и обнулить FileReferenceList - person sanchez; 31.03.2014
comment
Да, я пробовал и не работает, проблема не устранена. Я обновляю свой код (см. Вопрос) ... Спасибо за ваши усилия - person Guilherme Nascimento; 31.03.2014
comment
@GuilhermeNascimento Я не уверен, поможет ли это вам, но вы можете попробовать установить monsterdebugger demonsterdebugger.com. Это может дать вам больше информации. - person sanchez; 31.03.2014
comment
Да, это помогло мне, я переделал код, он освобождает почти всю память как MonsterDebbuger, см. Результаты: 1) Firefox / Safari (Flash-плагин 12.0.0.77): запускается с 9 МБ, увеличивается до 135 МБ и заканчивается на 17Мб. 2) Google Chrome (PepperFlash 12.0.0.70): начинается с 12 Мб, увеличивается до 132 Мб и заканчивается 17 Мб. 3) Рабочий стол (версия проигрывателя 10/12 без запуска CS5): начинается с 6 МБ, увеличивается до 185 МБ и заканчивается 185 МБ. - person Guilherme Nascimento; 02.04.2014
comment
Фиксированный тип: @ san.chez Спасибо, мне помог MonsterDebugger. Нам действительно нужно позаботиться о GC. Возможно, я куплю Flash Builder (мне сказали, что он идеально подходит для выявления причин такого рода проблем), спасибо за ваше внимание! +1 для вас - person Guilherme Nascimento; 02.04.2014
comment
Извините, что снова звоню вам, но я кое-что нашел: с FileReferenceList.fileList, если я так сделал FileReferenceList.fileList[5] = null; (когда шестой файл больше не используется) Флэш-память немедленно освобождает этот конкретный FileReference. Это также помогло FlashPlayer на рабочем столе. Внезапно я был так счастлив. - person Guilherme Nascimento; 02.04.2014

Даже если вы обнуляете каждую ссылку на объект, он не будет немедленно удален из памяти. Вам также необходимо удалить прослушиватели событий. Кроме того, никогда не используйте «безымянные» функции ... сложнее удалить прослушиватель, когда событие вызывает безымянную функцию. Итак, создайте новую функцию и вызовите ее. Например:

test.contentLoaderInfo.addEventListener(Event.COMPLETE, contentLoaderInfoComplete);
...
function contentLoaderInfoComplete(e:Event){
    test.contentLoaderInfo.removeEventListener(Event.COMPLETE, contentLoaderInfoComplete);
    test.unload();
    test = null;
}

Это очистит память.

person Zhafur    schedule 30.03.2014
comment
Потому что вы ожидаете, что сборщик мусора мгновенно очистит память. Этого не случится. GC НЕ очищает память немедленно. Если честно, вам не стоит беспокоиться об использовании памяти, если вы сделаете то, что мы сказали, установив для ссылок значение null и удалив прослушиватели событий, тогда в вашей программе не будет утечки памяти. - person Zhafur; 30.03.2014
comment
@ san.chez, спасибо за правку, уже поздно, и я испортил код! :) - person Zhafur; 30.03.2014
comment
Я вообще null ставил, где-то упустил? - person Guilherme Nascimento; 30.03.2014
comment
Вы должны удалить прослушиватели событий и использовать функции NAMED, пожалуйста, обновите свой код в своем вопросе. - person Zhafur; 30.03.2014
comment
@ san.chez Но я сказал, я попробовал это, и это не сработало ... Я отредактировал свой вопрос ... - person Guilherme Nascimento; 30.03.2014
comment
НИКОГДА не записывайте функцию в другую функцию ... это просто плохая практика, и я все еще вижу некоторые безымянные функции в вашем коде. - person Zhafur; 30.03.2014
comment
Я обнаружил, что проблема в FileReference, я отредактировал свой вопрос, не могли бы вы мне помочь? - person Guilherme Nascimento; 31.03.2014

Я достиг своей цели, если я так сделал FileReferenceList.fileList[5] = null; (когда "шестой файл" больше не используется) Флэш-память немедленно освобождает этот конкретный FileReference.

Другими словами:

Это не работает:

private var file:FileReference;
...
file = FileReferenceList.fileList[5];
...
file = null;

Но это сработало:

FileReferenceList.fileList[5] = null;

Работал на всех Desktop / Plugins / PepperFlash.

См. Рабочий код:

package {
    import flash.net.FileReferenceList;
    import flash.net.FileReference;
    import flash.net.FileFilter;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.display.Sprite;

    public class Main extends Sprite
    {
        private var listFiles:Array;
        private var allTypes:Array;
        private var fileRef:FileReferenceList;
        private var tmpFile:FileReference;
        private var i:uint=0;
        private var j:uint=0;
        private var timer:uint;
        private var imageTypes:FileFilter;
        private var enable:Boolean;

        public function Main()
        {
            imageTypes   = new FileFilter(
                "Images (*.JPG;*.JPEG;*.JPE;)", "*.jpg; *.jpeg; *.jpe;"
            );
            listFiles   = [];
            allTypes    = [imageTypes];

            eventBrowse(true);
        }

        private function eventBrowse(a:Boolean):void
        {
            enable = a;
            if(a===true) {
                stage.addEventListener(MouseEvent.CLICK, browse);

                fileRef = new FileReferenceList();
                fileRef.addEventListener(Event.SELECT, select);
            } else {
                fileRef.removeEventListener(Event.SELECT, select);
                fileRef = null;

                stage.removeEventListener(MouseEvent.CLICK, browse);
            }
        }

        private function browse(e:MouseEvent):void
        {
            if(enable===true) {
                fileRef.browse(allTypes);
            }
        }

        private function select(e:Event):void
        {
            listFiles = fileRef.fileList;

            eventBrowse(false);

            i=0;
            j=listFiles.length;

            if(j>0) {
                loadNextFile();
            }
        }

        private function loadNextFile():void
        {
            if(!(i<j)) {
                listFiles = null;
                trace("Free memory???");
                trace("--------------");
                trace("listFiles:"+ listFiles);
                trace("allTypes:" + allTypes);
                trace("fileRef:" + fileRef);
                trace("tmpFile:" + tmpFile);
                trace("i:" + i);
                trace("j:" + j);
                trace("timer:" + timer);
                trace("--------------");
                eventBrowse(true);
                return;
            }

            tmpFile = listFiles[i];
            trace("Initiate load:" + tmpFile.name);
            tmpFile.addEventListener(Event.COMPLETE, loadedFile);
            tmpFile.load();
        }

        private function loadedFile(f:Event):void
        {
            trace(listFiles);
            trace("Finished load:" + tmpFile.name);
            tmpFile.removeEventListener(Event.COMPLETE, loadedFile);

            tmpFile = null;
            listFiles[i] = null;

            i++;
            loadNextFile();
        }
    }
}
person Community    schedule 02.04.2014

Проблема заключается в сочетании всего перечисленного выше.

  1. Вам необходимо удалить прослушиватели событий вручную. Хотя можно использовать слабые ссылки, лучше, если вы возьмете за привычку отслеживать регистрируемых слушателей и всегда отменять их регистрацию должным образом. Таким образом вы сможете избежать утечек памяти (не совсем утечки памяти, но с аналогичным эффектом), о которых вы не ожидали или не думали.

  2. Вы создаете слушателей событий в цикле и повторно используете одну и ту же функцию для их обработки. Если вы это сделаете, вы должны каким-то образом получить ссылку на исходный загрузчик и удалить из него прослушиватель событий. Я понятия не имею, как вы пытались включить ответ Жафура, но если вы повторно использовали ссылку на файл для каждого нового файла, это будет причиной того, что он все еще не работает. Возможно, вы сможете обновить свой пример, приведенный выше, с помощью кода, который у вас есть в настоящее время, чтобы мы могли критиковать дальше.

  3. Вы никогда не должны принудительно использовать gc (сборщик мусора), если вам нужно это сделать, у вас есть проблемы в другом месте, которые вы должны решить вместо этого, как упоминалось в san.chez. Принудительный сбор мусора - хороший способ увидеть, что вы слишком быстро создаете слишком много объектов. Если вы видите, что использование памяти сильно снижается после принудительного запуска сборщика мусора, вы, вероятно, сделали это и должны переписать свой код, чтобы более эффективно использовать новые .

Судя по объему памяти, который вы израсходовали при создании тонны маленьких файлов или нескольких очень больших файлов, возможно, вы также можете рассказать нам об этом больше.

person David Dumke    schedule 31.03.2014
comment
1 - Я сделал это, и это связано с проблемой, проблема связана с filerefence.load (), независимо от того, были ли события (или нет). / 2 - Для этого я использовал пакеты и классы. Однако проблема заключается в том, что проблема заключается в FileReference. / 3 - код редактировал, посмотрите как было (под вопросом). - И снова повторяю, проблема возникает только с FileReference.load. - person Guilherme Nascimento; 31.03.2014