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); }
/// <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); }
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); }
/// <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); }
/// <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); }
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); }
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); }
public void TaskCanOnlyResolveOnce() { UnityTask t = new UnityTask(); t.Then((o) => Console.WriteLine("Task Fulfilled")); t.Resolve(); t.Resolve(); }
/// <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; }
/// <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; }