Обработчик событий объекта локального таймера - PullRequest
5 голосов
/ 05 мая 2011

У меня есть следующий код в функции класса:

public function foo():void
{
    var timer:Timer = new Timer(10000,1);
    timer.addEventListener(TimerEvent.TIMER_COMPLETE,onTimerComplete);
    timer.start();
}

public function onTimerComplete(e:TimerEvent):void
{
  // do stuff
}

Приведенный выше код работает большую часть времени, но меня беспокоит, что произойдет, если таймер получит мусор?Возможно ли, что onTimerComplete никогда не сработает, потому что нет других ссылок на таймер?

Я знаю, что у таймера есть внутренний список обработчиков, но это не помешает ему быть GC.

Ответы [ 4 ]

1 голос
/ 05 января 2012

В Интернете есть некоторые ссылки на то, что таймеры запуска никогда не собираются, например, :

Просто чтобы прояснить: даже если у вас нет ссылок на таймер,пока таймер работает, он не будет собирать мусор (представьте, что среда выполнения хранит ссылку на запущенные таймеры).

от Арно Гурдола из Adobe AIR Team

но мне не удалось найти авторитетный источник.

Вероятно, лучше не полагаться на это специальное поведение, а вместо этого сделать timer переменной уровня класса.

Ответы, указывающие на то, что слушатели событий удерживают таймер от сбора мусора, неверны.Ссылка от таймера до функции слушателя (onTimerComplete), поэтому, если таймер достижим, функция слушателя не будет собирать мусор, но не наоборот.Это легко проверить:

<?xml version="1.0" encoding="utf-8"?>
<s:Application
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="application1_creationCompleteHandler(event)">

<fx:Script>
    <![CDATA[
private var _gcTimer:Timer;

protected function application1_creationCompleteHandler(event:FlexEvent):void {
    var timer:Timer = new Timer(30, 4);
    timer.addEventListener(TimerEvent.TIMER, onTimer, false, 0, true);

    var sprite:Sprite = new Sprite();
    sprite.addEventListener(Event.ENTER_FRAME, onSprite, false, 0, true);

    _gcTimer = new Timer(59, 1);
    _gcTimer.addEventListener(TimerEvent.TIMER, garbageCollect);

    timer.start();
    _gcTimer.start();
}

private function onTimer(event:TimerEvent):void {
    trace("timer");
}

private function onSprite(event:Event):void {
    trace("sprite");
}
]]>
</fx:Script>
</s:Application>

Вывод:

спрайт
таймер
спрайт
таймер
сбор мусора
таймер
таймер

0 голосов
/ 05 мая 2011

По сути, ваш таймер в любом случае вызывает метод onTimerComplete один раз, так что зачем это GCed.
В любом случае вы играете с чем-то очень близким к закрытию JavaScipt. Закрытие - это функция, которая утратила свою сферу применения. Когда что-то теряет область видимости, это становится очень трудно для GC, особенно если к нему все еще подключен прослушиватель событий. Бессмысленно в вашем случае, потому что он работает только один раз.
Хорошей практикой кодирования было бы обнуление объекта после того, как с ним покончено.
Кроме того, еще одна вещь о вашем коде.
Это неправильно.

timer.addEventListener(TimerEvent.COMPLETE,onTimerComplete);

Должно быть

timer.addEventListener(TimerEvent.TIMER_COMPLET,onTimerComplete);


Если вы переместите объект таймера в область видимости класса, он не будет GCed.

public var timer:Timer = new Timer(10000,1);
public function foo():void
{
    this.timer.addEventListener(TimerEvent.TIMER_COMPLETE,this.onTimerComplete);
    this.timer.start();
}

public function onTimerComplete(e:TimerEvent):void
{
  // do stuff
}
0 голосов
/ 05 мая 2011

Я бы избегал массива antiGarbage, если вы уже не видели проблему, и она волшебным образом решает ее, потому что она добавляет дополнительную сложность, чтобы иметь дело с 12 месяцами.

У меня не было никаких проблем с событиемСлушатели AS3 и диспетчеры событий не могут соединиться друг с другом, пока создаются объекты.Одна важная вещь, на которую следует обратить внимание, - это создание объекта, который застрял в ожидании (прослушивании) чего-то, что уже было отправлено ранее при инициализации, и поэтому он пропустил вызов (отправленное событие) и зависает на неопределенный срок.

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

0 голосов
/ 05 мая 2011

Если вы беспокоитесь о сборке мусора, можете ли вы просто поместить таймер в массив, чтобы сохранить ссылку на него?

var antiGarbage:Array = [];
var timer:Timer = new Timer(10000, 1);

antiGarbage[antiGarbage.length] = timer;

Я не думаю, что проблема есть, но я уверен, что вам придетсяdo:

timer.removeEventListener(TimerEvent.COMPLETE, onTimerComplete);

Чтобы таймер был готов к GC.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...