Пример #1
0
        /// <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));
        }
Пример #2
0
 internal TaskStateChangedEventArgs(AsyncTask task, State state)
 {
     Task         = task;
     CurrentState = state;
 }
Пример #3
0
 protected virtual int CompareCore(AsyncTask otherTask)
 {
     return(0); // Having the same priority by default.
 }
Пример #4
0
 protected virtual TaskMergeInstruction CanMergeWithCore(AsyncTask otherTask)
 {
     return(TaskMergeInstruction.KeepBoth); // Keeping both tasks by default.
 }
Пример #5
0
 /// <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));
 }
Пример #6
0
 /// <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));
 }
Пример #7
0
 /// <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));
 }