Flex的线程类
Adobe Flash player的运行时环境不能支持多线程,除了非常特殊的扩展操作。Flash player使用了古老的逐帧式单线程独立执行模式。这就意味着在绘制ui和处理用户交互的时候会直接阻塞数据处理或其他重量级操作。flex框架的ui实现了一个标准的无效更新模式这样可以减轻大量ui重绘对组件的影响。ui组件还具有一个calllater方法,但是没有相应的后端数据处理。 转载: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 threads are 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 work but 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 update after 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> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |