Flex的线程类

来源:互联网 发布:如何定制淘宝客app 编辑:程序博客网 时间:2024/06/05 13:31

Adobe Flash player的运行时环境不能支持多线程,除了非常特殊的扩展操作。Flash player使用了古老的逐帧式单线程独立执行模式。这就意味着在绘制ui和处理用户交互的时候会直接阻塞数据处理或其他重量级操作。flex框架的ui实现了一个标准的无效更新模式这样可以减轻大量ui重绘对组件的影响。ui组件还具有一个calllater方法,但是没有相应的后端数据处理。

Thread.as类在flex项目中可以被任何一个flex类使用作为一个线程工作。简单的创建一个worker方法做一个单一的计数工作,它通常是在一个等待的工作队列中使用。然后创建一个Thread类的实例提供给worker作为第一个参数。记得保证worker线程是非常轻量级的,做的事情越少越好。workder方法会被重复的调用,直到返回值为true,说明工作已经完成。对于这个类的使用逻辑需要注意的一点是,要清楚什么时候调用worker方法能不阻碍flash player的运行。这样才能让后台处理数据,而用户依然可以与ui交互。

你可以提供一个work完成的方法。这样可以在工作结束后调用这个方法。

在实际应用中还要考虑多个线程并行执行的问题。注意分配给每个线程的执行时间。但是如果你有很多个线程或者是一个workder方法需要大量的执行时间的情况下你仍有可能消耗完所有的资源。
运行例子
源代码

转载:http://bbs.9ria.com/thread-73420-1-1.html


Thread.as

package com.dreamingwell.util{import flash.events.Event;import flash.events.EventDispatcher;import flash.system.System;import flash.utils.setTimeout;import mx.core.FlexGlobals;import mx.core.UIComponent;import mx.managers.SystemManager;import mx.rpc.IResponder;dynamic public class Thread extends EventDispatcher{/* Statics *//** Event type dispatched when the thread completes its work */public static const THREAD_COMPLETE_EVENT:String = "threadCompleteEvent";/** Event type dispatched when the thread will begin work in the next frame */public static const THREAD_STARTING_EVENT:String = "threadStartingEvent";/** Event type dispatched when the thread has manually stopped */public static const THREAD_STOPPED_EVENT:String = "threadStoppedEvent";/** The calculated time in ms that each frame is allowed; from Flash Player's framesPerSecond */private static var timePerFrame:Number = -1;/** The percent, as a number between 0 - 100, of time alloted in each frame to all thread's executions */public static var percentThreadExecutionTimePerFrame:Number = 50;/** The currently running number of threads */protected static var numberOfActiveThreads:Number = 0;/* Local Data References */private var _inProgress:Boolean = false;private var token:Object;private var workFunction:Function;private var completeFunction:Function;/** Determines whether this thread is currently in progress */public function get inProgress():Boolean {return _inProgress;}/** * This is class is used to create a "thread" of work. Supply a "work" function, that performs a tiny amount * of work, and returns a boolean as to whether the thread is complete. The "complete" function will be called when the  * work function returns that it has completed. * <Br><Br> * This thread object is the only argument passed to the work and complete functions. Thread is a dynamic object, * so you can add any property to it you like. For example, you can do the following: * <Br><Br> * var workerThread:Thread = new Thread(workerFunction); * <br>workerThread.token = myTokenObject; * <br>workerThread.someRandomId = idObject; * <Br> * <br>private function workerFunction(thread:Thread):Boolean { * <Br> * <br> var workQueueCompleted:Boolean = false; * <Br>.... * <Br> *  *  *  *   return workQueueCompleted; * } *  *  * @workFunction The function that will be called repeatedly. Keep the execution time of this function to * an absolute minimum. It should take one argument, which will be this thread instance. Thread is a dynamic * class, so you can manually add any property you'd like to be used in the worker function. The worker function * should return "true" when all available work has been completed; thus ending the execution of this thread. *  * @completeFunction The function that will be called once the worker thread has completed. *  * @autoStart A boolean flag as to whether the thread should start in the immediately following frame. If you set this false * you must manually call the start() method.  *  *   * */public function Thread(workFunction:Function, completeFunction:Function = null, autoStart:Boolean = true){/* Store given token */this.token = token;this.workFunction = workFunction;this.completeFunction = completeFunction;/* Setup the time allowed per execution period */if(timePerFrame == -1) {timePerFrame = 1000  / (FlexGlobals.topLevelApplication as UIComponent).stage.frameRate;}/* Auto start */if(autoStart)start();}/** Starts this thread's execution, only if it is not already in progress. */public function start():void {if(_inProgress)return;_inProgress = true;/* Increment the active threads */numberOfActiveThreads++;/* Dispatch a starting event */dispatchEvent(new Event(THREAD_STARTING_EVENT));setTimeout(doWork,1);}/** Ends this thread's execution prematurely; only if this thread is in progress. */public function stop():void {if(!_inProgress)return;_inProgress = false;/* Decrement the number of active threads */numberOfActiveThreads--;/* Dispatch an event to say this thread will no longer be doing work */dispatchEvent( new Event(THREAD_STOPPED_EVENT));}/** Performs each unit of work, by calculating the available remaining time, and calling * the worker function. */protected function doWork():void {/* get the start time */var startTime:Date = new Date();var currentTime:Date = new Date();/* A first loop, to allow at least one work block to go through per frame, in case too many threadsare running */var firstLoop:Boolean = true;/* Calculate the time alloted for this threads execution in this frame */var timePerFrame:Number = (Thread.timePerFrame * (percentThreadExecutionTimePerFrame / 100) ) / numberOfActiveThreads;/* loop until alloted time has lapsed, allow at least one loop */while( _inProgress && (startTime.time + timePerFrame > currentTime.time || firstLoop)) {firstLoop = false;/* Do the work function, and then evaluate whether it's complete */if(workFunction(this)) {/* Tell this not to */_inProgress = false;/* Decrement the number of active threads */numberOfActiveThreads--;/* Do complete  work */threadComplete();break;}/* Update to the new time */currentTime = new Date();}if(_inProgress) setTimeout(doWork,1);}/** Calls the completeFunction and dispatches the complete event */protected function threadComplete():void {if(completeFunction != null)completeFunction(this);dispatchEvent(new Event(THREAD_COMPLETE_EVENT));}}}

ThreadExamples.mxml

<?xml version="1.0" encoding="utf-8"?><s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"    xmlns:s="library://ns.adobe.com/flex/spark"    xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" viewSourceURL="srcview/index.html"><fx:Script><![CDATA[import com.dreamingwell.util.Thread;import mx.controls.Alert;/* Queue of objects on which to work */private var workQueue:Array = new Array();/* Number of iterations of work to do */[Bindable] private var iterations:Number = 10000;/* Number of iterations completed */[Bindable] private var iterationsCompleted:Number = 0;/* Flag to state when we're working, to disable buttons. */[Bindable] private var inProgress:Boolean = false;protected function threadedButton_clickHandler(event:MouseEvent):void{/* Reset the iteration count */iterationsCompleted = 0;/* Set this as in progress */inProgress = true;var thread:Thread = new Thread(threadedWorker,threadComplete);thread.someRandomPropertyName = new Object(); // you can set any property you like on the thread; its dynamic}protected function singleThreadButton_clickHandler(event:MouseEvent):void{/* Reset the iteration count */iterationsCompleted = 0;/* Call the same threaded worker function that does a small amount of workbut without using the thread class. Will interupt the UI, and make UI seem frozen */for(var i:Number = 0; i < iterations; i++) {threadedWorker(null); }threadComplete(null);}protected function threadedWorker(thread:Thread):Boolean {/* doing our heavy lifting here. Notice that you can change this number to any value large or small, and the UI remains responsive.*/for(var count:Number = 0; count < 100000; count++) {}/* Now increment the iterations completed count */iterationsCompleted++;/* Now update the progress bar, which will actually only visibly updateafter this frame has exited. */progressBar.setProgress( iterationsCompleted , iterations);/* If this is a threaded instance, check the iteration count and return */if(thread != null)return iterationsCompleted == iterations;/* This is not a threaded instance, just return false, doesn't matter */return false;}protected function threadComplete(thread:Thread):void {/* Turn off in progress */inProgress = false;Alert.show("Completed " + iterations + " iterations!");}]]></fx:Script><fx:Declarations><!-- Place non-visual elements (e.g., services, value objects) here --></fx:Declarations><s:layout><s:VerticalLayout/></s:layout><s:Label>1) Click the "Perform Threaded Work" button. Notice that the progress bar updates, and the browser does not freeze. </s:Label><s:Label>2) Click the "Perform Non-Threaded Work". Notice that the entire flash player freezes, possibly including the browser. The progress bar does not update. Wait until execution completes.</s:Label><s:Label>3) Right click to view source. </s:Label><s:HGroup><s:Button id="threadedButton" label="Perform Threaded Work" click="threadedButton_clickHandler(event)"  enabled="{!inProgress}" /><s:Button id="singleThreadButton" label="Perform Non-Threaded Work" click="singleThreadButton_clickHandler(event)" enabled="{!inProgress}"/></s:HGroup><mx:ProgressBar id="progressBar" indeterminate="false" mode="manual" maximum="{iterations}" minimum="0" /></s:Application>


原创粉丝点击