    /**
     * @class Ext.util.TaskRunner
     * Provides the ability to execute one or more arbitrary tasks in a multithreaded
     * manner.  Generally, you can use the singleton {@link Ext.TaskMgr} instead, but
     * if needed, you can create separate instances of TaskRunner.  Any number of
     * separate tasks can be started at any time and will run independently of each
     * other. Example usage:
     *
    // Start a simple clock task that updates a div once per second
    var updateClock = function(){
        Ext.fly('clock').update(new Date().format('g:i:s A'));
    }
    var task = {
        run: updateClock,
        interval: 1000 //1 second
    }
    var runner = new Ext.util.TaskRunner();
    runner.start(task);

    // equivalent using TaskMgr
    Ext.TaskMgr.start({
        run: updateClock,
        interval: 1000
    });

     *
     * Also see {@link Ext.util.DelayedTask}.
     *
     * @constructor
     * @param {Number} interval (optional) The minimum precision in milliseconds supported by this TaskRunner instance
     * (defaults to 10)
     */
    Ext.util.TaskRunner = function(interval){
        interval = interval || 10;
        var tasks = [],
        	removeQueue = [],
        	id = 0,
        	running = false,

        	// private
        	stopThread = function(){
    	        running = false;
    	        clearInterval(id);
    	        id = 0;
    	    },

        	// private
        	startThread = function(){
    	        if(!running){
    	            running = true;
    	            id = setInterval(runTasks, interval);
    	        }
    	    },

        	// private
        	removeTask = function(t){
    	        removeQueue.push(t);
    	        if(t.onStop){
    	            t.onStop.apply(t.scope || t);
    	        }
    	    },

        	// private
        	runTasks = function(){
    	    	var rqLen = removeQueue.length,
    	    		now = new Date().getTime();

    	        if(rqLen > 0){
    	            for(var i = 0; i < rqLen; i++){
    	                tasks.remove(removeQueue[i]);
    	            }
    	            removeQueue = [];
    	            if(tasks.length < 1){
    	                stopThread();
    	                return;
    	            }
    	        }
    	        for(var i = 0, t, itime, rt, len = tasks.length; i < len; ++i){
    	            t = tasks[i];
    	            itime = now - t.taskRunTime;
    	            if(t.interval <= itime){
    	                rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
    	                t.taskRunTime = now;
    	                if(rt === false || t.taskRunCount === t.repeat){
    	                    removeTask(t);
    	                    return;
    	                }
    	            }
    	            if(t.duration && t.duration <= (now - t.taskStartTime)){
    	                removeTask(t);
    	            }
    	        }
    	    };

        /**
         * Starts a new task.
         * @method start
         * @param {Object} task A config object that supports the following properties:
         * run : FunctionThe function to execute each time the task is run. The
         * function will be called at each interval and passed the args argument if specified.  If a
         * particular scope is required, be sure to specify it using the scope argument.
         * interval : NumberThe frequency in milliseconds with which the task
         * should be executed.
         * args : Array(optional) An array of arguments to be passed to the function
         * specified by run.
         * scope : Object(optional) The scope (this reference) in which to execute the
         * run function. Defaults to the task config object.
         * duration : Number(optional) The length of time in milliseconds to execute
         * the task before stopping automatically (defaults to indefinite).
         * repeat : Number(optional) The number of times to execute the task before
         * stopping automatically (defaults to indefinite).
         *
         * @return {Object} The task
         */
        this.start = function(task){
            tasks.push(task);
            task.taskStartTime = new Date().getTime();
            task.taskRunTime = 0;
            task.taskRunCount = 0;
            startThread();
            return task;
        };

        /**
         * Stops an existing running task.
         * @method stop
         * @param {Object} task The task to stop
         * @return {Object} The task
         */
        this.stop = function(task){
            removeTask(task);
            return task;
        };

        /**
         * Stops all tasks that are currently running.
         * @method stopAll
         */
        this.stopAll = function(){
            stopThread();
            for(var i = 0, len = tasks.length; i < len; i++){
                if(tasks[i].onStop){
                    tasks[i].onStop();
                }
            }
            tasks = [];
            removeQueue = [];
        };
    };

    /**
     * @class Ext.TaskMgr
     * @extends Ext.util.TaskRunner
     * A static {@link Ext.util.TaskRunner} instance that can be used to start and stop arbitrary tasks.  See
     * {@link Ext.util.TaskRunner} for supported methods and task config properties.
     *
    // Start a simple clock task that updates a div once per second
    var task = {
        run: function(){
            Ext.fly('clock').update(new Date().format('g:i:s A'));
        },
        interval: 1000 //1 second
    }
    Ext.TaskMgr.start(task);

     * @singleton
     */
    Ext.TaskMgr = new Ext.util.TaskRunner();