A helper class inspired by the .NET 4.0 Task object and javascript flow libraries such as Q
예제 #1
0
        public void TaskAllMethodCombinesTasksInParallel()
        {
            const int taskCount = 10;
            const int taskTime = 500; //ms
            const float tolerance = 50; //ms
            const int testLimit = 600; //ms
            UnityTask[] tasks = new UnityTask[taskCount];
            List<Thread> threads = new List<Thread>(taskCount);

            for (int i = 0; i < taskCount; i++)
            {
                UnityTask task = new UnityTask();
                tasks[i] = task;
                Thread thread = new Thread( () =>
                {
                    try
                    {
                        Thread.Sleep(taskTime);
                        task.Resolve();
                    }
                    catch (Exception e)
                    {
                        task.Reject(e);
                    }
                });
                thread.Start();
                threads.Add(thread);
            }

            DateTime startTime = DateTime.Now;
            object result = UnityTask.All(tasks).Result; // Result blocks until finished
            TimeSpan totalTime = DateTime.Now - startTime;

            Assert.AreEqual(totalTime.TotalMilliseconds, (float) taskTime, tolerance);
        }
예제 #2
0
    // Use this for initialization
    void Start()
    {
        var testEngine = new NUnitBasicTestEngine ("UnityTools");

        var testTask = new UnityTask( (task) => {
            testEngine.RunTests(new TestRunnerCallback(LogString, task));
        });

        testTask.Then(
            onFulfilled: (o) => LogString("All tests succeeded. UnityTools works on this device!"),
            onFailure: (ex) => LogString("Some tests failed. UnityTools does not work on this device.")
        );
    }
예제 #3
0
        public void TaskAllSequentialMethodCombinesTasksSequentially()
        {
            const int taskCount = 10;
            const int taskTime = 50; //ms
            const float tolerance = 50; //ms
            int tasksExecuted = 0;
            int accessCounter = 0;
            Func<UnityTask>[] tasks = new Func<UnityTask>[taskCount];
            List<Thread> threads = new List<Thread>(taskCount);

            for (int i = 0; i < taskCount; i++)
            {
                int i_ = i; // Copy i for lambdas

                UnityTask task = new UnityTask();
                Thread thread = new Thread( (object count) =>
                {
                    try
                    {
                        int count_ = (int)count;

                        Assert.AreEqual(accessCounter, 0, "Two tasks are executing simulaniously");
                        accessCounter++;

                        Assert.AreEqual(tasksExecuted, count_, "Tasks executed should be equal to the current index");
                        Thread.Sleep(taskTime);
                        Assert.AreEqual(tasksExecuted, count_, "Tasks executed should be equal to the current index");

                        tasksExecuted++;

                        accessCounter--;
                        task.Resolve();
                    }
                    catch (Exception e)
                    {
                        task.Reject(e);
                    }
                });

                tasks[i_] = () => { thread.Start(i_); return task; };

                threads.Add(thread);
            }

            DateTime startTime = DateTime.Now;
            object result = UnityTask.AllSequential(tasks).Result; // Result blocks until finished
            TimeSpan totalTime = DateTime.Now - startTime;

            Assert.AreEqual((float) taskTime * taskCount, totalTime.TotalMilliseconds , tolerance);
        }
예제 #4
0
        /// <summary>
        /// Combines multiple tasks of the same type into one callback and runs them sequentially. On failure the failure callback is called immediately
        /// and the result of the other tasks is discarded.
        /// </summary>
        /// <param name="tasks">A series of tasks to execute in sequential orders</param>
        private static UnityTask AllSequential(IDispatcher dispatcher, params Func <UnityTask>[] tasks)
        {
            if (tasks == null || tasks.Length == 0)
            {
                return(new UnityTask(dispatcher).Resolve());
            }

            UnityTask     combinedTask      = new UnityTask(dispatcher);
            List <Action> sequentialActions = new List <Action>();

            int activeTaskCount = tasks.Length;

            object[] taskResults = new object[activeTaskCount];

            for (int i = 0; i < tasks.Length; i++)
            {
                int taskCount = i;

                sequentialActions.Add(() =>
                {
                    UnityTask task = tasks[taskCount]();

                    task.Then(
                        onFulfilled: (object result) =>
                    {
                        taskResults[taskCount] = result;

                        if (taskCount == sequentialActions.Count - 1)
                        {
                            // Last task
                            combinedTask.Resolve(taskResults);
                        }
                        else
                        {
                            sequentialActions[taskCount + 1]();
                        }
                    },
                        onFailure: (Exception e) =>
                    {
                        combinedTask.Reject(e);
                    }
                        );
                });
            }

            sequentialActions[0]();

            return(combinedTask);
        }
예제 #5
0
        /// <summary>
        /// Combines multiple tasks of the same type into one callback and runs them simultaneously. On failure the failure callback is called immediately
        /// and the result of the other tasks is discarded.
        /// </summary>
        /// <param name="tasks">A series of tasks to execute in parallel</param>
        private static UnityTask All(IDispatcher dispatcher, params UnityTask[] tasks)
        {
            if (tasks == null || tasks.Length == 0)
            {
                return(new UnityTask(dispatcher).Resolve());
            }

            UnityTask combinedTask = new UnityTask(dispatcher);

            int activeTaskCount = tasks.Length;

            object[] taskResults     = new object[activeTaskCount];
            bool     tasksSucceeding = true;

            for (int i = 0; i < tasks.Length; i++)
            {
                UnityTask task      = tasks[i];
                int       taskCount = i;

                task.Then(
                    onFulfilled: (object result) =>
                {
                    if (!tasksSucceeding)
                    {
                        return;
                    }

                    taskResults[taskCount] = result;

                    activeTaskCount--;
                    if (activeTaskCount == 0)
                    {
                        combinedTask.Resolve(taskResults);
                    }
                },
                    onFailure: (Exception ex) =>
                {
                    // Only reject the task the first time
                    if (tasksSucceeding)
                    {
                        combinedTask.Reject(ex);     // Bail if one of the task errors out
                    }
                    tasksSucceeding = false;
                }
                    );
            }

            return(combinedTask);
        }
예제 #6
0
        /// <summary>
        /// Combines multiple tasks of the same type into one callback and runs them simultaneously. On failure the failure callback is called immediately
        /// and the result of the other tasks is discarded.
        /// </summary>
        /// <param name="tasks">A series of tasks to execute in paralell</param>
        public static UnityTask <T[]> All(params UnityTask <T>[] tasks)
        {
            // Cast the tasks down to the non generic version for code reuse
            UnityTask[] nonGenericTasks = tasks.Cast <UnityTask>().ToArray();

            // Call non generic version of All
            UnityTask       combinedTask = UnityTask.All(nonGenericTasks);
            UnityTask <T[]> outputTask   = new UnityTask <T[]>();

            // Funnel the non generic task into a generic one
            combinedTask.Then(
                onFulfilled: o => outputTask.Resolve((T)o),
                onFailure: ex => outputTask.Resolve(ex)
                );

            return(outputTask);
        }
예제 #7
0
        public void TaskResultIsSynchronous()
        {
            const int taskTime = 500; //ms
            const int targetValue = taskTime; //ms
            const int tolerance = 10;

            DateTime startTime = DateTime.Now;

            UnityTask t = new UnityTask(task => { Thread.Sleep(taskTime); task.Resolve(); });
            var r = t.Result;

            TimeSpan totalTime = DateTime.Now - startTime;

            Assert.AreEqual((float) taskTime, totalTime.TotalMilliseconds , tolerance);
        }
예제 #8
0
        public void TaskDoesResolve()
        {
            object value = null;
            object targetValue = new object();

            UnityTask t = new UnityTask();
            t.Then((o) => value = o);

            t.Resolve(targetValue);

            Assert.That(value == targetValue);
        }
예제 #9
0
        public void TaskDoesNotify()
        {
            float value = 0f;
            float targetValue = 1f;

            UnityTask t = new UnityTask();
            t.Then(null, null, (p) => value = p);

            t.Notify(1f);

            Assert.That(Utils.Math.NearlyEqual(value, targetValue));
        }
예제 #10
0
        public void TaskDoesFail()
        {
            Exception value = null;
            Exception targetValue = new Exception();

            UnityTask t = new UnityTask();
            t.Then(null, (ex) => value = ex);

            t.Reject(targetValue);

            Assert.That(value == targetValue);
        }
예제 #11
0
        public void TaskDoesEndOnResolveAndReject()
        {
            bool value = false;
            bool targetValue = true;

            UnityTask t = new UnityTask();
            t.Then(onEnd: () => value = targetValue);

            t.Resolve(null);

            Assert.AreEqual(value, targetValue);

            value = false;

            t = new UnityTask();
            t.Then(onEnd: () => value = targetValue);

            t.Reject(null);

            Assert.AreEqual(value, targetValue);

            value = false;

            t = new UnityTask();
            t.Then(onEnd: () => value = targetValue);

            t.Notify(0f);

            Assert.AreNotEqual(value, targetValue);
        }
예제 #12
0
        public void TaskCanOnlyResolveOnce()
        {
            UnityTask t = new UnityTask();
            t.Then((o) => Console.WriteLine("Task Fulfilled"));

            t.Resolve();
            t.Resolve();
        }
예제 #13
0
        public void TaskCanOnlyRejectOnce()
        {
            UnityTask t = new UnityTask();
            t.Then(null, (o) => Console.WriteLine("Task Failed"));

            t.Reject(new Exception());
            t.Reject(new Exception());
        }
예제 #14
0
        /// <summary>
        /// Combines multiple tasks of the same type into one callback and runs them sequentially. On failure the failure callback is called immediately
        /// and the result of the other tasks is discarded.
        /// </summary>
        /// <param name="tasks">A series of tasks to execute in sequential orders</param>
        private static UnityTask AllSequential(IDispatcher dispatcher, params Func<UnityTask>[] tasks)
        {
            if (tasks == null || tasks.Length == 0)
            {
                return new UnityTask(dispatcher).Resolve();
            }

            UnityTask combinedTask = new UnityTask(dispatcher);
            List<Action> sequentialActions = new List<Action>();

            int activeTaskCount = tasks.Length;
            object[] taskResults = new object[activeTaskCount];

            for (int i = 0; i < tasks.Length; i++)
            {
                int taskCount = i;

                sequentialActions.Add(() =>
                {
                    UnityTask task = tasks[taskCount]();

                    task.Then(
                        onFulfilled: (object result) =>
                        {
                            taskResults[taskCount] = result;

                            if (taskCount == sequentialActions.Count - 1)
                            {
                                // Last task
                                combinedTask.Resolve(taskResults);
                            }
                            else
                            {
                                sequentialActions[taskCount+1]();
                            }
                        },
                        onFailure: (Exception e) =>
                        {
                            combinedTask.Reject(e);
                        }
                    );
                });

            }

            sequentialActions[0]();

            return combinedTask;
        }
예제 #15
0
        /// <summary>
        /// Combines multiple tasks of the same type into one callback and runs them simultaneously. On failure the failure callback is called immediately
        /// and the result of the other tasks is discarded.
        /// </summary>
        /// <param name="tasks">A series of tasks to execute in parallel</param>
        private static UnityTask All(IDispatcher dispatcher, params UnityTask[] tasks)
        {
            if (tasks == null || tasks.Length == 0)
            {
                return new UnityTask(dispatcher).Resolve();
            }

            UnityTask combinedTask = new UnityTask(dispatcher);

            int activeTaskCount = tasks.Length;
            object[] taskResults = new object[activeTaskCount];
            bool tasksSucceeding = true;

            for (int i = 0; i < tasks.Length; i++)
            {
                UnityTask task = tasks[i];
                int taskCount = i;

                task.Then(
                    onFulfilled: (object result) =>
                    {
                        if (!tasksSucceeding)
                            return;

                        taskResults[taskCount] = result;

                        activeTaskCount--;
                        if (activeTaskCount == 0)
                        {
                            combinedTask.Resolve(taskResults);
                        }

                    },
                    onFailure: (Exception ex) =>
                    {
                        // Only reject the task the first time
                        if (tasksSucceeding) {
                            combinedTask.Reject(ex); // Bail if one of the task errors out
                        }
                        tasksSucceeding = false;
                    }
                );
            }

            return combinedTask;
        }
예제 #16
0
 public TestRunnerCallback(Action<string> logAction, UnityTask parentTask)
 {
     _logAction = logAction;
     _parentTask = parentTask;
 }