示例#1
0
        /// <summary>
        /// Disallows the specified today.
        /// </summary>
        /// <param name="today">The today.</param>
        /// <param name="startTime">The start time.</param>
        /// <param name="endTime">The end time.</param>
        /// <param name="weekdays">The weekdays.</param>
        /// <returns>Returns true if execution should be allowed else false</returns>
        internal static bool Disallow(DateTime today, TimeSpan startTime, TimeSpan endTime, Weekdays weekdays)
        {
            TimeSpan now = today.TimeOfDay;

            ///Out of the time range with start and time on the same day
            return(((now < startTime || endTime < now) && startTime < endTime)
                   ///Out of time range and job time spanning across the days
                   || ((endTime < now && now < startTime) && endTime < startTime)
                   ///Not a valid weekday
                   || !Util.HasWeekday(weekdays, Util.GetWeekday(today.DayOfWeek)));
        }
示例#2
0
        /// <summary>
        /// Returns the nexts scedule from the specified date time
        /// </summary>
        /// <param name="from">From date time</param>
        /// <returns></returns>
        DateTime IRecur.Next(DateTime from)
        {
            DateTime original = from;

            while (true)
            {
                Weekdays thisDay = Utils.GetWeekday(from.DayOfWeek);
                ///If its all weekdays, just add the next day
                if (_weekdays == Weekdays.All)
                {
                    if (thisDay == Weekdays.Saturday)
                    {
                        from = from.AddDays((_repeat * 7) + 1);
                    }
                    else
                    {
                        from = from.AddDays(1);
                    }
                }
                else
                {
                    int d, i = (int)from.DayOfWeek;
                    ///Find number of days for the next valid weekday
                    for (d = 0; !Utils.HasWeekday(_weekdays, Utils.GetWeekday(i)); i++)
                    {
                        d++;
                    }
                    ///calculate next valid weekday to run the job
                    i = (d + (int)from.DayOfWeek) % 7;

                    ///if the next valid day is >= the from weekday simple add the day else going back to next week
                    if (i >= (int)from.DayOfWeek)
                    {
                        from = from.AddDays(d);
                    }
                    else
                    {
                        from = from.AddDays(d + (_repeat * 7));
                    }
                }
                ///If the date is same the one passed in the add a day
                if (original == from)
                {
                    from = from.AddDays(1);
                    continue;
                }
                return(from);
            }
        }
示例#3
0
        /// <summary>
        /// Runs the task.
        /// </summary>
        /// <param name="state">The state.</param>
        private void RunTask(object state)
        {
            if (!_isStarted)
            {
                return;
            }

            TaskWrapper taskWrapper = null;

            lock (_sync)
            {
                // if this is coming as part of the timer trigger close down the timer
                if (_timer != null)
                {
                    TraceInformation("Disabling the timer");
                    _timer.Change(Timeout.Infinite, Timeout.Infinite);
                }

                _jobsInQueue--;

                DateTime today = Now;
                TimeSpan now   = today.TimeOfDay;

                ///Check whether it is within the allowed time
                if (Time.Disallow(today, _dayStartTime, _dayEndTime, _weekdays))
                {
                    TraceInformation("Not allowed to run at this time");

                    ///If there are more queued items, release this thread task
                    if (_jobsInQueue > 0)
                    {
                        TraceInformation("Have more items in queue");
                        return;
                    }

                    ///If the number of thread running is more that minimum thread, remove 1 and return;
                    if (_freeTaskPool.Count > 0 && _allTasks.Count > MinInstances)
                    {
                        TraceInformation("Releasing a task");
                        taskWrapper = _freeTaskPool[0];
                        taskWrapper.Release();
                        _freeTaskPool.Remove(taskWrapper);
                        _allTasks.Remove(taskWrapper);
                    }


                    if (_timer == null)
                    {
                        TraceInformation("Timer created");
                        _timer = new Timer(new TimerCallback(RunTask), null, Timeout.Infinite, Timeout.Infinite);
                    }

                    ///Do it only for the last thread.
                    if (_parallelInstances == 0 && _allTasks.Count == MinInstances)
                    {
                        DateTime st = new DateTime(today.Year, today.Month, today.Day, _dayStartTime.Hours, _dayStartTime.Minutes, _dayStartTime.Seconds, DateTimeKind.Unspecified);

                        ///if today is not allowed weekday, move it to next start of the day
                        if (!Utils.HasWeekday(_weekdays, Utils.GetWeekday(today.DayOfWeek)) || today > st)
                        {
                            st = st.AddDays(1).Date; //Setting it to next day 12:00 AM
                        }
                        ///Find the differene by converting to UTC time to make sure daylight cutover are accounted
                        TimeSpan wait = TimeZoneInfo.ConvertTimeToUtc(st, _timeZoneInfo) - TimeZoneInfo.ConvertTimeToUtc(today, _timeZoneInfo);

                        ///This is for the timer job
                        _jobsInQueue++;
                        _timer.Change((long)wait.TotalMilliseconds, Timeout.Infinite);
                        //_timer.Change(_idlePollingPeriod, Timeout.Infinite);
                        TraceInformation("wait for {0} before it starts", wait);
                    }
                    return;
                }

                if (_freeTaskPool.Count == 0)
                {
                    AddTask(1);
                }

                if (_freeTaskPool.Count > 0)
                {
                    taskWrapper = _freeTaskPool[0];
                    _freeTaskPool.RemoveAt(0);
                }
                else
                {
                    ///There are no parallel capacity so exit
                    TraceInformation("There is no more thread capacity for this task runner");
                    return;
                }

                _parallelInstances++;
            }
            TraceInformation("Free Task {0}, All Task {1}, Parallel Instanse {2}, Queue {3}", _freeTaskPool.Count, _allTasks.Count, _parallelInstances, _jobsInQueue);

            ExecutionState executionState = taskWrapper.RunTask();

            switch (executionState)
            {
            case ExecutionState.Executed:
                //Since there is work it should also create one more instance for parallel tasking
                lock (_sync)
                {
                    ///Reduce the number of instances
                    _parallelInstances--;
                    ///Put back the task into the free pool
                    _freeTaskPool.Add(taskWrapper);
                    //Since executed successfully it should go back for execution
                    QueueTask();
                    //there is more capacity possible, put one more to work
                    if (_jobsInQueue + _parallelInstances < this.MaxInstances)
                    {
                        QueueTask();
                    }
                }
                RaiseComplete(taskWrapper.Context);
                break;

            case ExecutionState.Stop:
                //Since the task has indicated to stop, release it
                lock (_sync)
                {
                    ///Reduce the number of instances
                    _parallelInstances--;
                    _allTasks.Remove(taskWrapper);
                    _freeTaskPool.Remove(taskWrapper);
                    ///If that the last instance then stop the task
                    if (_jobsInQueue == 0 && _parallelInstances == 1)
                    {
                        Stop();
                    }
                }
                break;

            case ExecutionState.Recycle:
                //Since the task has indicated to recycle it, release it and add new.
                lock (_sync)
                {
                    ///Reduce the number of instances
                    _parallelInstances--;

                    _allTasks.Remove(taskWrapper);
                    _freeTaskPool.Remove(taskWrapper);
                    AddTask(1);
                    QueueTask();
                }
                break;

            case ExecutionState.Idle:
            case ExecutionState.Exception:    //If there is an unhandled exception we should treat it as idle else it will lead to CPU racing
                //This is tough task :-), not enough work to do, start firing ;-)
                lock (_sync)
                {
                    ///Reduce the number of instances
                    _parallelInstances--;

                    ///Put back the task into the free pool
                    _freeTaskPool.Add(taskWrapper);
                    //There are other items in the queue do nothing come out.
                    if (_jobsInQueue > 0)
                    {
                        break;
                    }

                    ///Fire 1 task, save resources ONLY if task return Idle
                    if (_allTasks.Count > MinInstances)
                    {
                        taskWrapper = _freeTaskPool[0];
                        taskWrapper.Release();
                        _freeTaskPool.Remove(taskWrapper);
                        _allTasks.Remove(taskWrapper);
                    }
                    ///This is the last thread, put a timer since there is no work, lets wait for 5 seconds.
                    ///This can be further imporved by having increasing delay i.e. wait for 5, 10, 15 when we
                    ///get work reset it to 5 secs
                    if (_timer == null)
                    {
                        _timer = new Timer(new TimerCallback(RunTask), null, Timeout.Infinite, Timeout.Infinite);
                    }
                    ///Wait for idle period to see whether there is something to do
                    ///Do it only for the last thread and there is no job in the queue
                    if (_parallelInstances == 0 && _jobsInQueue == 0)
                    {
                        ///This is for the timer job
                        _jobsInQueue++;
                        _timer.Change((long)_idlePollingPeriod, Timeout.Infinite);
                        TraceInformation("Is in timer mode");
                    }
                }
                break;

            default:
                ///This could be for any new state
                lock (_sync)
                {
                    ///Reduce the number of instances
                    _parallelInstances--;
                    ///Put back the task into the free pool
                    _freeTaskPool.Add(taskWrapper);
                    QueueTask();
                }
                break;
            }
        }
示例#4
0
        /// <summary>
        /// Runs the task.
        /// </summary>
        /// <param name="state">The state.</param>
        private void RunTask(object state)
        {
            ///Task not started, call should never come here
            if (_timer == null)
            {
                return;
            }

            DateTime today = Now;

            ///Not in the limit of the date time range
            if (today > _endDateTime)
            {
                Stop();
                return;
            }

            ///Sleep until the interval duration before start time
            if (today < _startDateTime)
            {
                TimeSpan wait = TimeZoneInfo.ConvertTimeToUtc(_startDateTime, _timeZoneInfo).Subtract(TimeZoneInfo.ConvertTimeToUtc(today, _timeZoneInfo));
                TraceInformation("will wait for {0} before it starts", wait);
                _timer.Change((long)wait.TotalMilliseconds, _interval);
                return;
            }

            ///Not in the range of time of the day or avalid weekday
            if (Time.Disallow(today, _dayStartTime, _dayEndTime, _weekdays))
            {
                DateTime st = new DateTime(today.Year, today.Month, today.Day, _dayStartTime.Hours, _dayStartTime.Minutes, _dayStartTime.Seconds, DateTimeKind.Unspecified);

                ///If its not an allowed weekday, wait until next start of day
                if (!Utils.HasWeekday(_weekdays, Utils.GetWeekday(today.DayOfWeek)) || today > st)
                {
                    st = st.AddDays(1).Date;
                }

                ///Find the differene by converting to UTC time to make sure daylight cutover are accounted
                TimeSpan wait = TimeZoneInfo.ConvertTimeToUtc(st, _timeZoneInfo) - TimeZoneInfo.ConvertTimeToUtc(today, _timeZoneInfo);

                //TimeSpan wait = st.Subtract(now);
                TraceInformation("will wait for {0} before it starts", wait);
                _timer.Change((long)wait.TotalMilliseconds, _interval);
                return;
            }

            if (_recurrence > 0 || _recurrence == -1)
            {
                ///Stop the timer
                _timer.Change(Timeout.Infinite, _interval);
                ExecutionState executionState = _task.RunTask();

                switch (executionState)
                {
                case ExecutionState.Executed:
                    RaiseComplete(_task.Context);
                    break;

                case ExecutionState.Stop:
                    _task.Release();
                    Stop();
                    return;

                case ExecutionState.Recycle:
                    _task.Release();
                    _task = new TaskWrapper(this.TaskType, new ExecutionContext(Parameters, this));
                    break;
                }

                if (_recurrence != -1)
                {
                    _recurrence--;
                }

                ///Resume the timer
                _timer.Change(Interval, _interval);
            }
            else
            {
                Stop();
                TraceInformation("stopped because the reccurence is 0 ");
            }
        }
示例#5
0
        DateTime IRecur.Next(DateTime from)
        {
            DateTime original = from;

            while (true)
            {
                ///Set the valid month
                from = Utils.GetValidMonth(_months, from);

                //First week
                if ((_weeks & Weeks.First) == Weeks.First)
                {
                    while (from.Day < 8)
                    {
                        if (Utils.HasWeekday(_weekdays, Utils.GetWeekday(from.DayOfWeek)) &&
                            from != original)
                        {
                            return(from);
                        }
                        from = from.AddDays(1);
                    }
                }
                //Second week
                if ((_weeks & Weeks.Second) == Weeks.Second)
                {
                    while (from.Day < 15 && from.Day > 7)
                    {
                        if (Utils.HasWeekday(_weekdays, Utils.GetWeekday(from.DayOfWeek)) &&
                            from != original)
                        {
                            return(from);
                        }
                        from = from.AddDays(1);
                    }
                }
                //Third week
                if ((_weeks & Weeks.Third) == Weeks.Third)
                {
                    while (from.Day < 22 && from.Day > 14)
                    {
                        if (Utils.HasWeekday(_weekdays, Utils.GetWeekday(from.DayOfWeek)) &&
                            from != original)
                        {
                            return(from);
                        }
                        from = from.AddDays(1);
                    }
                }
                //Both Fourth & Last week
                if ((_weeks & (Weeks.Fourth | Weeks.Last)) == (Weeks.Fourth | Weeks.Last))
                {
                    while (from.Day > 21)
                    {
                        if (Utils.HasWeekday(_weekdays, Utils.GetWeekday(from.DayOfWeek)) &&
                            from != original)
                        {
                            return(from);
                        }
                        from = from.AddDays(1);
                    }
                }
                else
                {
                    //Fourth week
                    if ((_weeks & Weeks.Fourth) == Weeks.Fourth)
                    {
                        while (from.Day < 29 && from.Day > 21)
                        {
                            if (Utils.HasWeekday(_weekdays, Utils.GetWeekday(from.DayOfWeek)) &&
                                from != original)
                            {
                                return(from);
                            }
                            from = from.AddDays(1);
                        }
                    }
                    //Last
                    if ((_weeks & Weeks.Last) == Weeks.Last)
                    {
                        int lastWeekDay = GetLastWeekStartDay(from);
                        while (from.Day >= lastWeekDay)
                        {
                            if (Utils.HasWeekday(_weekdays, Utils.GetWeekday(from.DayOfWeek)) &&
                                from != original)
                            {
                                return(from);
                            }
                            from = from.AddDays(1);
                        }
                    }
                }
                from = from.AddDays(1);
            }
        }