private void UpgradeTask(CancellationToken cancelToken) { IUpgradeTasksModel upgradeTaskDataModel = ServiceLocator.Current.GetInstance <IUpgradeTasksModel>(); var deviceComparer = new DeviceEqualityComparer(); try { FtpServer.Instance.NewDataConnection += FtpServer_NewDataConnection; FtpServer.Instance.ClosedDataConnection += FtpServer_ClosedDataConnection; FtpServer.Instance.SentData += FtpServer_SentData; upgradeTaskDataModel.RefillDataAsync().Wait(); //upgradeTaskDataModel.Data.Where( upgradeTaskDataModel.Select( t => t.Status == UpgradeStatus.InProgress && (t.LastStartTime == null || t.LastStartTime < _serviceStartTime)).ToList() .ForEach(task => MarkUpgradeTaskTBD(upgradeTaskDataModel, task)); while (true) { _token.ThrowIfCancellationRequested(); // 刪除被使用者標記要刪除且非運行中的 Task //var tasksToBeRemoved = upgradeTaskDataModel.Data.Where( var tasksToBeRemoved = upgradeTaskDataModel.Select( t => t.DeletedByUser && t.Status != UpgradeStatus.InProgress).ToList(); if (tasksToBeRemoved != null) { upgradeTaskDataModel.Delete(tasksToBeRemoved); } // 挑選出狀態為運行中但超過 20 秒未動作的 tasks,將其標記為 TBD upgradeTaskDataModel.Select( t => t.Status == UpgradeStatus.InProgress && (t.LastUpdateTime == null || (DateTime.Now - (DateTime)t.LastUpdateTime).TotalSeconds > 20)).ToList() .ForEach(t => { MarkUpgradeTaskTBD(upgradeTaskDataModel, t); }); //var upgradeTasks = upgradeTaskDataModel.Data.Where( // t => t.Status != UpgradeStatus.Removed).ToList(); var upgradeTasks = upgradeTaskDataModel.Select( t => t.Status != UpgradeStatus.Removed, t => t.Device, t => t.UpgradeFile).ToList(); if (upgradeTasks != null) { var devices = (from t in upgradeTasks where t.Device.online == 1 select t.Device).Distinct(deviceComparer).ToList(); //List<Task> tasks = new List<Task>(); foreach (var device in devices) { _token.ThrowIfCancellationRequested(); //tasks.Add(Task.Run(() => UpgradeTaskForEachDevice(upgradeTaskDataModel, device, cancelToken))); UpgradeTaskForEachDevice(upgradeTaskDataModel, device, cancelToken); } //Task.WaitAll(tasks.ToArray()); } Thread.Sleep(100); } } catch (OperationCanceledException) { } finally { FtpServer.Instance.NewDataConnection -= FtpServer_NewDataConnection; FtpServer.Instance.ClosedDataConnection -= FtpServer_ClosedDataConnection; FtpServer.Instance.SentData -= FtpServer_SentData; } }
// ConcurrentQueue<Task> updateTaskQueueForUpgradeTask = new ConcurrentQueue<Task>(); private void UpgradeTaskForEachDevice(IUpgradeTasksModel upgradeTaskDataModel, Device device, CancellationToken cancelToken) { // 刪除被使用者標記要刪除且非運行中的 Task //var tasksToBeRemoved = upgradeTaskDataModel.Data.Where( var tasksToBeRemoved = upgradeTaskDataModel.Select( t => t.DeletedByUser && t.Status != UpgradeStatus.InProgress).ToList(); if (tasksToBeRemoved != null) { upgradeTaskDataModel.Delete(tasksToBeRemoved); } //var updateTasksPerDevice = upgradeTaskDataModel.Data.Where( // t => t.DeviceID == device.id && t.Status != UpgradeStatus.Removed var updateTasksPerDevice = upgradeTaskDataModel.Select( t => t.DeviceID == device.id && t.Status != UpgradeStatus.Removed, t => t.Device, t => t.UpgradeFile ).OrderByDescending(t => t.UpgradeFile.filetype); UpgradeTask candidateTask = null; bool stopTrace = false; try { foreach (var task in updateTasksPerDevice) { if (candidateTask == null || candidateTask.UpgradeFile.filetype != task.UpgradeFile.filetype) { //if (candidateTask != null && candidateTask.Status == UpgradeStatus.TBD) //{ // put candidateTask to working queue //PutUpgradeTaskInWorkingQueue(upgradeTaskDataModel, candidateTask); //} candidateTask = task; stopTrace = false; } else if (!stopTrace) { // similar tasks: // case 1.1: (x, T) // remove // (1, T) // pick // case 1.2: (1, C or W) // (1, T) // remove // case 1.3: (1, C or W) // (2, T) // pick if 1 is C // case 2.1: (x, T) // remove // (x, T) // remove // (1, T) // pick // case 2.2: (1, C or W) // (x, T) // remove // (1, T) // remove // case 2.3: (1, C or W) // (x, T) // remove // (2, T) // pick if 1 is C if (task.Status == UpgradeStatus.TBD) { MarkUpgradeTaskRemoved(upgradeTaskDataModel, task); } else { // Complete or Working if (candidateTask.UpgradeID == task.UpgradeID) { MarkUpgradeTaskRemoved(upgradeTaskDataModel, candidateTask); } else { if (task.Status != UpgradeStatus.Complete) { candidateTask = task; } } stopTrace = true; } } } } catch (Exception) { return; } //if (candidateTask != null && candidateTask.Status == UpgradeStatus.TBD) //{ // // put candidateTask to working queue // //PutUpgradeTaskInWorkingQueue(upgradeTaskDataModel, candidateTask); //} if (device.online == 0) { return; } var taskInProgress = (from t in updateTasksPerDevice.AsParallel() where t.Status == UpgradeStatus.InProgress select t).FirstOrDefault(); if (taskInProgress == null) { candidateTask = (from t in updateTasksPerDevice.AsParallel() where t.Status == UpgradeStatus.TBD && !t.DeletedByUser orderby t.ID select t).FirstOrDefault(); if (candidateTask != null) { PutUpgradeTaskInWorkingQueue(upgradeTaskDataModel, candidateTask); } } }