/// <summary> /// Schedules the specified task for repeated <i>fixed-rate execution</i>, /// beginning at the specified time. Subsequent executions take place at /// approximately regular intervals, separated by the specified period. /// /// <para>In fixed-rate execution, each execution is scheduled relative to the /// scheduled execution time of the initial execution. If an execution is /// delayed for any reason (such as garbage collection or other background /// activity), two or more executions will occur in rapid succession to /// "catch up." In the long run, the frequency of execution will be /// exactly the reciprocal of the specified period (assuming the system /// clock underlying <tt>Object.wait(long)</tt> is accurate). As a /// consequence of the above, if the scheduled first time is in the past, /// then any "missed" executions will be scheduled for immediate "catch up" /// execution. /// /// </para> /// <para>Fixed-rate execution is appropriate for recurring activities that /// are sensitive to <i>absolute</i> time, such as ringing a chime every /// hour on the hour, or running scheduled maintenance every day at a /// particular time. It is also appropriate for recurring activities /// where the total time to perform a fixed number of executions is /// important, such as a countdown timer that ticks once every second for /// ten seconds. Finally, fixed-rate execution is appropriate for /// scheduling multiple repeating timer tasks that must remain synchronized /// with respect to one another. /// /// </para> /// </summary> /// <param name="task"> task to be scheduled. </param> /// <param name="firstTime"> First time at which task is to be executed. </param> /// <param name="period"> time in milliseconds between successive task executions. </param> /// <exception cref="IllegalArgumentException"> if {@code firstTime.getTime() < 0} or /// {@code period <= 0} </exception> /// <exception cref="IllegalStateException"> if task was already scheduled or /// cancelled, timer was cancelled, or timer thread terminated. </exception> /// <exception cref="NullPointerException"> if {@code task} or {@code firstTime} is null </exception> public virtual void ScheduleAtFixedRate(TimerTask task, DateTime firstTime, long period) { if (period <= 0) { throw new IllegalArgumentException("Non-positive period."); } Sched(task, firstTime.Ticks, period); }
/// <summary> /// Schedules the specified task for execution after the specified delay. /// </summary> /// <param name="task"> task to be scheduled. </param> /// <param name="delay"> delay in milliseconds before task is to be executed. </param> /// <exception cref="IllegalArgumentException"> if <tt>delay</tt> is negative, or /// <tt>delay + System.currentTimeMillis()</tt> is negative. </exception> /// <exception cref="IllegalStateException"> if task was already scheduled or /// cancelled, timer was cancelled, or timer thread terminated. </exception> /// <exception cref="NullPointerException"> if {@code task} is null </exception> public virtual void Schedule(TimerTask task, long delay) { if (delay < 0) { throw new IllegalArgumentException("Negative delay."); } Sched(task, DateTimeHelperClass.CurrentUnixTimeMillis() + delay, 0); }
/// <summary> /// Adds a new task to the priority queue. /// </summary> internal virtual void Add(TimerTask task) { // Grow backing store if necessary if (Size_Renamed + 1 == Queue.Length) { Queue = Arrays.CopyOf(Queue, 2 * Queue.Length); } Queue[++Size_Renamed] = task; FixUp(Size_Renamed); }
/// <summary> /// Schedules the specified task for repeated <i>fixed-rate execution</i>, /// beginning after the specified delay. Subsequent executions take place /// at approximately regular intervals, separated by the specified period. /// /// <para>In fixed-rate execution, each execution is scheduled relative to the /// scheduled execution time of the initial execution. If an execution is /// delayed for any reason (such as garbage collection or other background /// activity), two or more executions will occur in rapid succession to /// "catch up." In the long run, the frequency of execution will be /// exactly the reciprocal of the specified period (assuming the system /// clock underlying <tt>Object.wait(long)</tt> is accurate). /// /// </para> /// <para>Fixed-rate execution is appropriate for recurring activities that /// are sensitive to <i>absolute</i> time, such as ringing a chime every /// hour on the hour, or running scheduled maintenance every day at a /// particular time. It is also appropriate for recurring activities /// where the total time to perform a fixed number of executions is /// important, such as a countdown timer that ticks once every second for /// ten seconds. Finally, fixed-rate execution is appropriate for /// scheduling multiple repeating timer tasks that must remain synchronized /// with respect to one another. /// /// </para> /// </summary> /// <param name="task"> task to be scheduled. </param> /// <param name="delay"> delay in milliseconds before task is to be executed. </param> /// <param name="period"> time in milliseconds between successive task executions. </param> /// <exception cref="IllegalArgumentException"> if {@code delay < 0}, or /// {@code delay + System.currentTimeMillis() < 0}, or /// {@code period <= 0} </exception> /// <exception cref="IllegalStateException"> if task was already scheduled or /// cancelled, timer was cancelled, or timer thread terminated. </exception> /// <exception cref="NullPointerException"> if {@code task} is null </exception> public virtual void ScheduleAtFixedRate(TimerTask task, long delay, long period) { if (delay < 0) { throw new IllegalArgumentException("Negative delay."); } if (period <= 0) { throw new IllegalArgumentException("Non-positive period."); } Sched(task, DateTimeHelperClass.CurrentUnixTimeMillis() + delay, period); }
/// <summary> /// Establishes the heap invariant (described above) assuming the heap /// satisfies the invariant except possibly for the leaf-node indexed by k /// (which may have a nextExecutionTime less than its parent's). /// /// This method functions by "promoting" queue[k] up the hierarchy /// (by swapping it with its parent) repeatedly until queue[k]'s /// nextExecutionTime is greater than or equal to that of its parent. /// </summary> private void FixUp(int k) { while (k > 1) { int j = k >> 1; if (Queue[j].NextExecutionTime <= Queue[k].NextExecutionTime) { break; } TimerTask tmp = Queue[j]; Queue[j] = Queue[k]; Queue[k] = tmp; k = j; } }
/// <summary> /// Establishes the heap invariant (described above) in the subtree /// rooted at k, which is assumed to satisfy the heap invariant except /// possibly for node k itself (which may have a nextExecutionTime greater /// than its children's). /// /// This method functions by "demoting" queue[k] down the hierarchy /// (by swapping it with its smaller child) repeatedly until queue[k]'s /// nextExecutionTime is less than or equal to those of its children. /// </summary> private void FixDown(int k) { int j; while ((j = k << 1) <= Size_Renamed && j > 0) { if (j < Size_Renamed && Queue[j].NextExecutionTime > Queue[j + 1].NextExecutionTime) { j++; // j indexes smallest kid } if (Queue[k].NextExecutionTime <= Queue[j].NextExecutionTime) { break; } TimerTask tmp = Queue[j]; Queue[j] = Queue[k]; Queue[k] = tmp; k = j; } }
/// <summary> /// Schedule the specified timer task for execution at the specified /// time with the specified period, in milliseconds. If period is /// positive, the task is scheduled for repeated execution; if period is /// zero, the task is scheduled for one-time execution. Time is specified /// in Date.getTime() format. This method checks timer state, task state, /// and initial execution time, but not period. /// </summary> /// <exception cref="IllegalArgumentException"> if <tt>time</tt> is negative. </exception> /// <exception cref="IllegalStateException"> if task was already scheduled or /// cancelled, timer was cancelled, or timer thread terminated. </exception> /// <exception cref="NullPointerException"> if {@code task} is null </exception> private void Sched(TimerTask task, long time, long period) { if (time < 0) { throw new IllegalArgumentException("Illegal execution time."); } // Constrain value of period sufficiently to prevent numeric // overflow while still being effectively infinitely large. if (System.Math.Abs(period) > (Long.MaxValue >> 1)) { period >>= 1; } lock (Queue) { if (!Thread.NewTasksMayBeScheduled) { throw new IllegalStateException("Timer already cancelled."); } lock (task.@lock) { if (task.State != TimerTask.VIRGIN) { throw new IllegalStateException("Task already scheduled or cancelled"); } task.NextExecutionTime = time; task.Period = period; task.State = TimerTask.SCHEDULED; } Queue.Add(task); if (Queue.Min == task) { Monitor.Pulse(Queue); } } }
/// <summary> /// Schedules the specified task for execution at the specified time. If /// the time is in the past, the task is scheduled for immediate execution. /// </summary> /// <param name="task"> task to be scheduled. </param> /// <param name="time"> time at which task is to be executed. </param> /// <exception cref="IllegalArgumentException"> if <tt>time.getTime()</tt> is negative. </exception> /// <exception cref="IllegalStateException"> if task was already scheduled or /// cancelled, timer was cancelled, or timer thread terminated. </exception> /// <exception cref="NullPointerException"> if {@code task} or {@code time} is null </exception> public virtual void Schedule(TimerTask task, DateTime time) { Sched(task, time.Ticks, 0); }