/// <summary> /// An ISchedulerThread implementation calls this method so scheduler /// starts to process the next task in the queue, if there is any. Note /// that this method is meant to process only one task in queue. The /// implementation of ISchedulerThread is free to call this method again /// in a fashion that matches its task fetching behavior. /// </summary> /// <param name="waitIfTaskQueueIsEmpty">This parameter is only used if /// the task queue is empty at the time this method is invoked. When the /// task queue becomes empty, setting this to true will cause this call /// to block until either the next task becomes available, or when the /// scheduler is requested to shutdown.</param> /// <returns>This method returns true if the task queue is not empty, or /// false otherwise. Note that this method returns false when scheduler /// begins to shutdown, even when the task queue is not empty.</returns> public bool ProcessNextTask(bool waitIfTaskQueueIsEmpty) { AsyncTask nextTask = null; IEnumerable <AsyncTask> droppedTasks = null; lock (taskQueue) { if (taskQueueUpdated) { // The task queue has been updated since the last time // a task was processed, it might need compacting. droppedTasks = CompactTaskQueue(); ReprioritizeTasksInQueue(); taskQueueUpdated = false; } if (taskQueue.Count > 0) { nextTask = taskQueue[0]; taskQueue.RemoveAt(0); } else { // No more task in queue, reset wait handle. waitHandles[(int)EventIndex.TaskAvailable].Reset(); } } if (droppedTasks != null) { // Only notify listeners of dropping tasks here instead of // within CompactTaskQueue method. This way the lock on task // queue will not be held up for a prolonged period of time. // foreach (var droppedTask in droppedTasks) { NotifyTaskStateChanged(droppedTask, TaskStateChangedEventArgs.State.Discarded); } } if (nextTask != null) { ProcessTaskInternal(nextTask); return(true); // This method should be called again. } // If there's no more task and wait is not desired... if (!waitIfTaskQueueIsEmpty) { return(false); // The task queue is now empty. } // Block here if ISchedulerThread requests to wait. // ReSharper disable once CoVariantArrayConversion int index = WaitHandle.WaitAny(waitHandles); // If a task becomes available, this method returns true to indicate // that an immediate call may be required (subjected to the decision // of the ISchedulerThread's implementation). In the event that the // scheduler is shutting down, then this method returns false. // return(index == ((int)EventIndex.TaskAvailable)); }
internal TaskStateChangedEventArgs(AsyncTask task, State state) { Task = task; CurrentState = state; }
protected virtual int CompareCore(AsyncTask otherTask) { return(0); // Having the same priority by default. }
protected virtual TaskMergeInstruction CanMergeWithCore(AsyncTask otherTask) { return(TaskMergeInstruction.KeepBoth); // Keeping both tasks by default. }
/// <summary> /// Call this method to determine the relative priority of two AsyncTask /// objects. DynamoScheduler makes use of this method to determine the /// order in which AsyncTask objects are sorted in its internal task queue. /// </summary> /// <param name="otherTask">A task to compare this task with.</param> /// <returns>Returns -1 if this AsyncTask object should be processed /// before the other AsyncTask; returns 1 if this AsyncTask object should /// be processed after the other AsyncTask; or 0 if both AsyncTask objects /// have the same priority and can be processed in the current order. /// </returns> /// internal int Compare(AsyncTask otherTask) { return(ReferenceEquals(this, otherTask) ? 0 : CompareCore(otherTask)); }
/// <summary> /// This method is called by DynamoScheduler when it compacts the task /// queue. The result of this call indicates if either of the tasks in /// comparison should be dropped from the task queue, or both should be /// kept. Tasks that are discarded during this phase will not be executed. /// </summary> /// <param name="otherTask">Another task to compare with.</param> /// <returns>Returns the comparison result. See Comparison enumeration /// for details of the possible values.</returns> /// internal TaskMergeInstruction CanMergeWith(AsyncTask otherTask) { return(ReferenceEquals(this, otherTask) ? TaskMergeInstruction.KeepBoth : CanMergeWithCore(otherTask)); }
/// <summary> /// Upon completion of the task, invoke the specified action /// </summary> /// <returns>An IDisposable representing the event subscription</returns> public static IDisposable Then(this AsyncTask task, AsyncTaskCompletedHandler action) { task.Completed += action; return(Disposable.Create(() => task.Completed -= action)); }