public static IEnumerable <IOperation> GetAllOperation(this ICompositeOperation compositeOperation) { var list = new List <IOperation>(); foreach (var operation in compositeOperation.Operations) { if (operation is ICompositeOperation compositeOperation2) { list.AddRange(compositeOperation2.GetAllOperation()); } else { list.Add(operation); } } return(list); }
/// <summary> /// Запуск последовательно /// </summary> /// <param name="operation"></param> /// <returns></returns> private OperationObject RunSerial(ICompositeOperation operation) { var operations = operation.GetOperations(); if (operations == null || operations.Length == 0) { throw new ArgumentException("No any operation to run ", "consequentOperations"); } // Инициализация int n = operations.Length; var tokenSource = new CancellationTokenSource(); var commonState = new InteropState(); var mockOperationObj = new OperationObject { OperationId = GetNewIndex() }; var mockInterop = new OperationInterop(mockOperationObj, tokenSource.Token, commonState); OperationObject[] conseqOperationObjects = new OperationObject[n]; // Создание объектов представления операций for (int i = 0; i < n; ++i) { conseqOperationObjects[i] = new OperationObject { Parent = mockOperationObj }; mockOperationObj.Children.Add(conseqOperationObjects[i]); } Task chainEnd = null; Task firstTask = null; bool finalSet = false; // Создание цепочки выполнения for (int i = 0; i < n; ++i) { // --> Переменные для замыкания var j = i; var thisOperation = operations[i]; var thisOperationObj = conseqOperationObjects[i]; var thisInterop = new OperationInterop(thisOperationObj, tokenSource.Token, commonState); // <-- thisOperationObj.OperationId = GetNewIndex(); thisOperationObj.Name = thisOperation.OperationInfo.Name; // Chain :: Выполнение операции if (chainEnd == null) { // Первая операция chainEnd = new Task(() => { mockOperationObj.Status = OperationStatus.Running; operation.OnChainStart(mockInterop); thisOperation.Execute(thisInterop); }, tokenSource.Token); firstTask = chainEnd; } else { // Цепляем следующие chainEnd = chainEnd.ContinueWith((_, __) => { tokenSource.Token.ThrowIfCancellationRequested(); thisOperation.Execute(thisInterop); }, null, tokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current); } // Chain :: Обработка законченной операции chainEnd = chainEnd.ContinueWith(et => { thisOperation.Dispose(); // Установка статуса собственной операции thisOperationObj.Status = et.Status.ToOperationStatus(); // Установка статуса главной репрезентативной операции if (!finalSet) { if (et.Status != TaskStatus.RanToCompletion) { // Любая операция завершилась неуспешно mockOperationObj.Status = et.Status.ToOperationStatus(); thisOperationObj.Exception = et.Exception; mockOperationObj.Exception = et.Exception; if (!IsBeingWatched(mockOperationObj)) { Notifier.Notify("Операция #" + mockOperationObj.OperationId, "Операция не завершена", null); } tokenSource.Cancel(); finalSet = true; } else if (j == n - 1) { // Последняя операция завершилась успешно mockOperationObj.Status = OperationStatus.RanToCompletion; mockOperationObj.Progress = 100; if (!IsBeingWatched(mockOperationObj)) { Notifier.Notify("Операция #" + mockOperationObj.OperationId, "Операция завершена", null); } tokenSource.Cancel(); finalSet = true; } } if (j < n - 1) { // Установка прогресса главной репрезентативной операции UpdateMockOperationProgress(mockOperationObj, n, j + 1); } }); thisOperationObj.Status = OperationStatus.Created; } chainEnd.ContinueWith(t => { operation.OnChainEnded(); operation.Dispose(); }); // Обработка и запуск выполнения цепочки mockOperationObj.Status = OperationStatus.Created; mockOperationObj.Added = DateTime.Now; mockOperationObj.Name = operation.OperationInfo.Name; AddOperation(mockOperationObj); AddUnit(mockOperationObj.OperationId, new OperationUnit { CancellationTokenSource = tokenSource, ChainEndTask = chainEnd }, operations); firstTask.Start(); return mockOperationObj; }
/// <summary> /// Запуск параллельно /// </summary> /// <param name="operation"></param> /// <returns></returns> private OperationObject RunParallel(ICompositeOperation operation) { var operations = operation.GetOperations(); if (operations == null || operations.Length == 0) { throw new ArgumentException("No any operation to run ", "consequentOperations"); } // Инициализация int n = operations.Length; var tokenSource = new CancellationTokenSource(); var commonState = new InteropState(); var mockOperationObj = new OperationObject { OperationId = GetNewIndex() }; var mockInterop = new OperationInterop(mockOperationObj, tokenSource.Token, commonState); OperationObject[] parallelOperationObjects = new OperationObject[n]; // Создание объектов представления операций for (int i = 0; i < n; ++i) { parallelOperationObjects[i] = new OperationObject { Parent = mockOperationObj }; mockOperationObj.Children.Add(parallelOperationObjects[i]); } List<Task> tasks = new List<Task>(); int finishedCount = 0; bool totalSuccess = true; bool canceled = false; // Создание цепочки выполнения for (int i = 0; i < n; ++i) { // текущая задача Task task = null; // --> Переменные для замыкания var j = i; var thisOperation = operations[i]; var thisOperationObj = parallelOperationObjects[i]; var thisInterop = new OperationInterop(thisOperationObj, tokenSource.Token, commonState); // <-- thisOperationObj.OperationId = GetNewIndex(); thisOperationObj.Name = thisOperation.OperationInfo.Name; // Запуск операции task = new Task(() => { thisOperationObj.Status = OperationStatus.Running; thisOperation.Execute(thisInterop); }, tokenSource.Token); // Обработка законченной операции task.ContinueWith(et => { thisOperation.Dispose(); finishedCount++; // Установка статуса собственной операции thisOperationObj.Status = et.Status.ToOperationStatus(); if (et.Status != TaskStatus.RanToCompletion) { thisOperationObj.Exception = et.Exception; totalSuccess = false; if (et.Status == TaskStatus.Canceled) { canceled = true; tokenSource.Cancel(); } } // Установка прогресса главной репрезентативной операции UpdateMockOperationProgress(mockOperationObj, n, finishedCount); // завершились все задачи // Установка статуса главной репрезентативной операции if (finishedCount == n) { if (totalSuccess) { // Последняя операция завершилась успешно mockOperationObj.Status = OperationStatus.RanToCompletion; mockOperationObj.Progress = 100; if (!IsBeingWatched(mockOperationObj)) { Notifier.Notify("Операция #" + mockOperationObj.OperationId, "Операция завершена", null); } } else { mockOperationObj.Status = canceled ? OperationStatus.Canceled : OperationStatus.Faulted; if (!IsBeingWatched(mockOperationObj)) { Notifier.Notify("Операция #" + mockOperationObj.OperationId, "Операция не завершена", null); } } tokenSource.Cancel(); operation.OnChainEnded(); operation.Dispose(); } }); thisOperationObj.Status = OperationStatus.Created; tasks.Add(task); } // Обработка и запуск выполнения цепочки mockOperationObj.Status = OperationStatus.Created; mockOperationObj.Added = DateTime.Now; mockOperationObj.Name = operation.OperationInfo.Name; AddOperation(mockOperationObj); AddUnit(mockOperationObj.OperationId, new OperationUnit { CancellationTokenSource = tokenSource }, operations); operation.OnChainStart(mockInterop); mockOperationObj.Status = OperationStatus.Running; foreach (Task task in tasks) { task.Start(); } return mockOperationObj; }
/// <summary> /// Запустить составную операцию /// </summary> /// <param name="operation">Составная операция</param> /// <exception cref="System.ArgumentException" /> public OperationObject Run(ICompositeOperation operation) { if (operation.IsParallel) return RunParallel(operation); else return RunSerial(operation); }
private IOperation CreateOperation(ICompositeOperation compositeOperation) => new AsyncOperationStateMachine(compositeOperation, _logger);
private static IOperation CreateOperation(ICompositeOperation compositeOperation) => new AsyncOperationStateMachine(compositeOperation);