/// <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;
        }