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

本文通过两个测试场景探讨了Flash中事件处理的执行顺序及函数执行的原子性特点,揭示了Flash代码执行线程的单一性及其事件驱动的本质。
近来写代码的时候,常常会担心代码的执行顺序,例如某个函数是否会被事件处理函数打断之类的,百度了一下,无果(这个已经早就预料到的了),关键时候还是得翻出我的英语老底,投靠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]
上面的探讨如有任何错误或疑惑,欢迎回复指正和讨论。
源码来自:https://pan.quark.cn/s/a4b39357ea24 《C++ Primer》作为C++编程领域中的一部权威著作,主要服务于初学者和经验丰富的开发者,致力于帮助他们深入掌握C++的核心知识。 第一章通常会详细讲解C++语言的基础概念和语法结构,包括变量的使用、数据类型的分类、常量的定义、运算符的应用以及基础的输入输出操作。 接下来,我们将对这一章中的核心知识点和可能的习题解答进行深入分析。 ### 1. 变量与数据类型在C++编程中,变量被视为存储数据的媒介。 每一个变量都必须预先声明其数据类型,常见的数据类型有整型(int)、浮点型(float)、双精度浮点型(double)以及字符型(char)。 例如:```cppint age = 25; // 声明一个整型变量age并赋予其初始值25float weight = 70.5f; // 声明一个浮点型变量weight并赋予其初始值70.5char grade = A; // 声明一个字符型变量grade并赋予其初始值A```### 2. 常量与字面量常量指的是不可更改的值,可以通过`const`关键字进行声明。 例如:```cppconst int MAX_SIZE = 100; // 声明一个整型常量MAX_SIZE,其值为100```字面量是指程序中直接书写的值,如`42`、`3.14`或`"Hello"`。 ### 3. 运算符C++提供了多种运算符,涵盖了算术运算符(+,-,*,/,%)、比较运算符(==,!=,<,>,<=,>=)、逻辑运算符(&&,||,!)以及赋值运算符(=,+=,-=,*=,/=,%=)等。 ### 4. 输入与输出在C++中,使用`std::cin`来...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值