Esempio n. 1
0
        /// <summary>
        /// Contructor for the EentTaskRunner
        /// </summary>
        /// <param name="name">Unique name of the task runner</param>
        /// <param name="taskType">.NET Type for the task</param>
        /// <param name="parameters">Parameters from the configuration</param>
        /// <param name="eventTopic">Name of the event topic</param>
        /// <param name="threadOption">ThreadOption for the task</param>
        /// <param name="timeout">Timeout of the runner before it stops</param>
        /// <param name="logType">TraceType filter for this runner</param>
        public EventTaskRunner(string name, Type taskType, Dictionary <string, object> parameters, string eventTopic, ThreadOption threadOption, int timeout, LogType logType) :
            base(name, taskType, parameters, logType)
        {
            eventTopic.NotNullOrEmpty(nameof(eventTopic));
            if (timeout < 1 || timeout > 10000)
            {
                throw new ArgumentOutOfRangeException("timeout", "timeout should be between 1 and 10,000 ms (10 sec)");
            }

            _timeout      = timeout;
            _eventTopic   = eventTopic;
            _threadOption = threadOption;
            _taskWrapper  = new TaskWrapper(taskType, new ExecutionContext(this.Parameters, this));

            if (threadOption == ThreadOption.BackgroundSerial)
            {
                _queue = new Queue <ExecutionContext>();
            }
            else
            {
                _syncEvent = new ManualResetEvent(true);
            }
        }
Esempio n. 2
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;
            }
        }
Esempio n. 3
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 ");
            }
        }
Esempio n. 4
0
 /// <summary>
 /// Stops this instance.
 /// </summary>
 public override void Stop()
 {
     _taskWrapper.Release();
     _taskWrapper = null;
 }