加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Flex的线程类

发布时间:2020-12-15 04:24:58 所属栏目:百科 来源:网络整理
导读:Adobe Flash player的运行时环境不能支持多线程,除了非常特殊的扩展操作。Flash player使用了古老的逐帧式单线程独立执行模式。这就意味着在绘制ui和处理用户交互的时候会直接阻塞数据处理或其他重量级操作。flex框架的ui实现了一个标准的无效更新模式这样

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读