2011-05-05 12 views
5

Tengo el siguiente código en una función de clase:temporizador objeto local Gestor de Eventos

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 
} 

El código anterior funciona la mayor parte del tiempo, pero mi preocupación es lo que sucede si el temporizador se recoge la basura? ¿Es posible que onTimerComplete nunca se active porque no hay otras referencias al temporizador?

Sé que el temporizador tiene una lista interna de controladores, pero eso no evitará que se someta a GC.

Respuesta

1

hay algunas referencias en la web a la ejecución de los temporizadores no se recoge la basura, e.g.:

Para que quede claro: incluso si no tiene referencias a un temporizador, siempre como el temporizador está en marcha , no será basura recolectada (piense en como si el tiempo de ejecución guardara una referencia a los temporizadores en ejecución).

por Arno Gourdol del AIR Adobe Equipo

pero no he sido capaz de encontrar una fuente autorizada.

Probablemente sea mejor no confiar en este comportamiento especial y en su lugar hacer de timer una variable de nivel de clase.

Las respuestas que sugieren que los detectores de eventos evitan que el temporizador sea recogido son incorrectas. La referencia es desde el temporizador hasta la función del oyente (onTimerComplete), de modo que si el temporizador es alcanzable, entonces la función del oyente no será recolectada como basura, pero no viceversa. Esto se puede probar fácilmente:

<?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> 

de salida:

sprites
temporizador
sprites
temporizador
Recogida de la basura
temporizador
temporizador

0

Si su preocupación es la recolección de basura, ¿puede simplemente poner el temporizador en una matriz para mantener la referencia a la misma?

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

antiGarbage[antiGarbage.length] = timer; 

No creo que hay una preocupación, sin embargo, bastante seguro de que tendría que hacer:

timer.removeEventListener(TimerEvent.COMPLETE, onTimerComplete); 

Para el temporizador para estar listo para GC.

0

Básicamente lo que está haciendo su temporizador es llamar al método onTimerComplete de todos modos una vez, así que ¿por qué preocuparse si es GCed?
En cualquier caso, está jugando con algo muy parecido a un cierre de JavaScipt. Un cierre es una función que ha perdido su alcance. Cuando algo pierde alcance, se vuelve muy difícil GC, especialmente porque aún tiene un detector de eventos adjunto. Inútil en su caso porque solo se ejecuta una vez.
Buenas prácticas de codificación sería anular el objeto después de que haya terminado con él.
Además, una cosa más sobre su código.
Esto está mal.

timer.addEventListener(TimerEvent.COMPLETE,onTimerComplete); 

Debe ser

timer.addEventListener(TimerEvent.TIMER_COMPLET,onTimerComplete); 


Si se mueve el objeto temporizador para el ámbito de la clase que no será 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

Mis co ncern es si la demora en el temporizador es demasiado larga, digamos miles de segundos si existe la posibilidad de que el temporizador se acumule y el onTimerComplete nunca se llame. –

+0

no debe ser GCed hasta que se elimine el detector de eventos. –

+0

¿Estás seguro de eso? Este artículo: http://gingerbinger.com/2010/07/actionscript-3-0-events-the-myth-of-useweakreference/ afirma que los oyentes no evitan que los despachadores reciban el servicio de GC. –

0

Me gustaría evitar la matriz antiGarbage a menos que ya haya visto un problema y que mágicamente lo resuelve porque agrega una complejidad adicional para hacer frente a 12 meses a partir de ahora.

No he tenido ningún problema con los oyentes del evento AS3 y los despachadores de eventos al no poder conectar entre sí mientras se crearon los objetos. Una cosa importante de tener en cuenta es crear un objeto que está atascado esperando (escuchando) algo que ya se envió antes en la inicialización, por lo que perdió la llamada (evento enviado) y se cuelga indefinidamente.

Si su temporizador aparece en las variables del depurador cuando se supone que debe estar en tic-tac y completando, entonces debería estar dorado.

Cuestiones relacionadas