/// <summary> /// Initializes the task manager /// </summary> public void Initialize() { _taskThreads.Clear(); var taskService = EngineContext.Current.Resolve <IScheduleTaskService>(); var scheduleTasks = taskService .GetAllTasks() .OrderBy(x => x.Seconds) .ToList(); foreach (var scheduleTask in scheduleTasks) { var taskThread = new TaskThread { Seconds = scheduleTask.Seconds }; //sometimes a task period could be set to several hours (or even days) //in this case a probability that it'll be run is quite small (an application could be restarted) //calculate time before start an interrupted task if (scheduleTask.LastStartUtc.HasValue) { //seconds left since the last start var secondsLeft = (DateTime.UtcNow - scheduleTask.LastStartUtc).Value.TotalSeconds; if (secondsLeft >= scheduleTask.Seconds) { //run now (immediately) taskThread.InitSeconds = 0; } else { //calculate start time //and round it (so "ensureRunOncePerPeriod" parameter was fine) taskThread.InitSeconds = (int)(scheduleTask.Seconds - secondsLeft) + 1; } } else { //first start of a task taskThread.InitSeconds = scheduleTask.Seconds; } taskThread.AddTask(scheduleTask); _taskThreads.Add(taskThread); } }
/// <summary> /// Hàm khởi tạo task manager với những cấu hình lấy từ file cấu hình. Đọc về danh sách các task trong database /// và gom nhóm, tạo các nhóm taskThread cần thiết /// /// Có thể gọi nhiều lần, nếu trong quá trình chạy của ứng dụng cấu hình task có thay đổi /// </summary> public void Initialize() { Stop(); //// khác ở đây : dừng các task đang có nếu có, nếu ta ko làm điều này sẽ khiến cho các taskThread vẫn sẽ chạy // Ta stop thì ít nhất cũng sẽ chỉ chỉ "để xổng" lần chạy cuối cùng, ko stop có thể khiến các taskThread cũ ko bị hủy và chạy song song _taskThreads.Clear(); var taskService = EngineContext.Current.Resolve<IScheduleTaskService>(); var scheduleTasks = taskService.GetAllTasks().OrderBy(p => p.Seconds) .ThenByDescending(p => p.RunWithAnotherTask).ToList(); // gom nhóm các Itask theo thời gian chờ chạy lại TaskThread taskThread = null; ScheduleTask prevTask = null; foreach (var scheduleTask in scheduleTasks) { if (taskThread == null || scheduleTask.Seconds != taskThread.Seconds || !scheduleTask.RunWithAnotherTask || !prevTask.RunWithAnotherTask) { taskThread = new TaskThread(scheduleTask.RunWithAnotherTask, scheduleTask.RunWithAnotherTask ? null : scheduleTask.Name) {Seconds = scheduleTask.Seconds}; _taskThreads.Add(taskThread); } taskThread.AddTask(new Task(scheduleTask)); prevTask = scheduleTask; } //sometimes a task period could be set to several hours (or even days). //in this case a probability that it'll be run is quite small (an application could be restarted) //we should manually run the tasks which weren't run for a long time // tìm ra những task thuộc loại có thời gian chờ dài và chưa được chạy trong khoảng thời gian // >= _notRunTasksInterval. Với những task này, ngoại trừ việc xếp lịch chạy thông thường ( task sẽ được chạy lần đầu tiên // sau Second giây ( >= _notRunTasksInterval ) kể từ thời điểm appStart, chúng ta sẽ xếp thêm 1 lịch chạy riêng để ưu // tiên cho các tast này chạy DUY NHẤT 1 lần sau thời điểm App Start được 5 phút, điều này là để ĐỀN BÙ cho task vì nó // đã ko chạy lâu quá rồi var notRunTasks = scheduleTasks.Where(t => t.Seconds >= _notRunTasksInterval && ( !t.LastStartUtc.HasValue || t.LastStartUtc.Value.AddSeconds(_notRunTasksInterval) < DateTime.UtcNow) ).ToList(); //create a thread for the tasks which weren't run for a long time if (notRunTasks.Count > 0) { taskThread = new TaskThread(true, null) { RunOnlyOnce = true, Seconds = 5*60 // 5 phút }; foreach (var task in notRunTasks) taskThread.AddTask(new Task(task)); _taskThreads.Add(taskThread); } }