关于Actionscript3的事件驱动代码执行机制

近来写代码的时候,常常会担心代码的执行顺序,例如某个函数是否会被事件处理函数打断之类的,百度了一下,无果(这个已经早就预料到的了),关键时候还是得翻出我的英语老底,投靠google吧。

以下是我自己设计的测试场景:

[b][size=medium][color=brown]测试场景1:[/color][/size][/b]
假设有类ExecutionTest, 代码如下:

package com.longpeijin.exec
{
import flash.display.Sprite;
import flash.events.Event;

public class ExecutionTest extends Sprite
{
public function ExecutionTest()
{
var obj:SystemHandler = new SystemHandler(this,"1");
var obj1:SystemHandler = new SystemHandler(this,"2");
this.dispatchEvent(new Event(SystemHandler.SYS_EVENT));
trace("Main function executed!");
}
}
}


和另外一个类SystemHandler:

package com.longpeijin.exec
{
import flash.events.Event;
import flash.events.EventDispatcher;

public class SystemHandler
{
public static const SYS_EVENT:String = "sysEvent";
private var name:String;

public function SystemHandler(obj:EventDispatcher, name:String)
{
obj.addEventListener(SYS_EVENT,onEvent);
this.name = name;
}

public function onEvent(event:Event):void{
trace("event handler executed! " + name);
}
}
}


简单来说就是ExecutionTest类的某个方法在执行的过程中发布了一次事件,紧接着其后又执行了一些代码,那么监听这个事件的事件处理程序会马上执行还是等待ExecutionTest执行完毕才执行呢?

输出结果如下:

event handler executed! 1
event handler executed! 2
Main function executed!


结果可以知道,在执行过程中发布一次时间,其实就是在事件监听链条上逐个执行事件处理程序,然后再返回主函数,跟普通的函数调用没有两样!

所以ExecutionTest类的构造函数等价于以下的样子:

package com.longpeijin.exec
{
import flash.display.Sprite;
import flash.events.Event;

public class ExecutionTest extends Sprite
{
public function ExecutionTest()
{
var obj:SystemHandler = new SystemHandler(this,"1");
var obj1:SystemHandler = new SystemHandler(this,"2");
obj.onEvent(null);
obj1.onEvent(null);
trace("Main function executed!");
}
}
}


[b][size=medium][color=brown]测试场景2:[/color][/size][/b]

另外一个我想知道的问题就是,假如有一个函数正在执行一个比较耗时的操作,这时候其他的一个对象发出了一次事件(例如一个网络资源下载完成了),而自身也有监听这个事件,那么这时当前函数的执行会被打断么?

于是我设计了以下的类EventTest:

package com.longpeijin.event
{
import flash.display.Loader;
import flash.display.MovieClip;
import flash.events.Event;
import flash.net.URLRequest;

public class EventTest extends MovieClip
{
public function EventTest()
{
super();
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("http://www.evolife.cn/wp-content/uploads/2010/06/iphone4display3.jpg"));
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
this.stage.frameRate = 20;
}



private function onEnterFrame(event:Event):void{
trace("On Enter frame start!");
//do something time consuming
var arr:Array = [];
for(var i:int;i<10000;i++){
arr.push(Math.random());
}
for each(var num:int in arr){
Math.sqrt(num*100);
}
trace("On Enter frame end!");
}

private function onComplete(event:Event):void{
trace("Resouces loaded!");
}
}
}


为了排除网络速度因素,我执行了该类10次,但每次的输出都有一个固定的片段:

On Enter frame start!
On Enter frame end!
Resouces loaded!
On Enter frame start!
On Enter frame end!

Resouces loaded!没有一次出现在On Enter frame start!和On Enter frame end!之间,换句话说,函数从来没有被打断过。

[size=medium][color=blue]之前也求教过一些高手,得知Flash的代码执行线程只有一个(这里指的是执行代码的线程,不包括下载网络资源的那些线程),有点类似底层CPU的时间片轮转执行,但轮转的并不是线程(因为主线程只有一个),而是各个对象的事件处理函数(Timer事件,Event.Complete事件,KeyboardEvent之类的),所以AVM的执行完全是事件驱动的。即使主MovieClip的构造函数(类似于Java中的main方法)执行完毕,程序不会像普通Java程序那样直接退出,而是空闲着等待着事件的发生,而且函数的执行是原子性的,任何时候不会被打断(除非AVM被崩掉或者你叉掉浏览器啦)。
换个角度来看Flash是不支持多线程的,所以6核、双核、单核的CPU执行起来,都只会用到其中的一个核心而已。[/color][/size]
上面的探讨如有任何错误或疑惑,欢迎回复指正和讨论。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值