public IFreeHierarchyObject UpdateSource(List <Info_Balance_FreeHierarchy_Description> descriptions, Dispatcher dispatcher,
                                                 Action onFieldChanged, out bool isAdded)
        {
            isAdded = false;

            //List<Info_Balance_FreeHierarchy_Description> descriptions = null;

            if (_balance != null && descriptions == null)
            {
                descriptions = ARM_Service.BL_GetFreeHierarchyBalanceDescritions(_balance.BalanceFreeHierarchy_UN);
            }

            var sections = ARM_Service.BL_GetFreeHierarchyBalanceSections(BalanceFreeHierarchyTypeID);

            if (sections == null || sections.Count == 0)
            {
                Manager.UI.ShowMessage("Не описаны разделы для данного типа баланса!");
                return(null);
            }

            var source = new List <BalanceFreeHierarchySectionRow>();
            var isExistsDescription = descriptions != null && descriptions.Count > 0;
            var tps        = EnumClientServiceDictionary.GetTps();
            var isFirst    = true;
            var isFirstRow = true;

            IFreeHierarchyObject result = null;

            foreach (var section in sections.Where(s => s.UseInTotalResult))
            {
                var row = new BalanceFreeHierarchySectionRow(section, dispatcher);
                if (isFirst)
                {
                    row.IsSelected = true;
                    isFirst        = false;
                }

                if (isExistsDescription)
                {
                    //Если есть описание данного баланса
                    foreach (var description in descriptions.Where(d => string.Equals(d.BalanceFreeHierarchySection_UN, section.BalanceFreeHierarchySection_UN)).OrderBy(d => d.SortNumber))
                    {
                        var isIntegral = false;
                        IFreeHierarchyObject hierarchyObject = null;
                        if (description.TI_ID.HasValue)
                        {
                            TInfo_TI ti;
                            if (!EnumClientServiceDictionary.TIHierarchyList.TryGetValue(description.TI_ID.Value, out ti) || ti == null)
                            {
                                continue;
                            }
                            hierarchyObject = ti;
                        }
                        if (description.IntegralTI_ID.HasValue)
                        {
                            isIntegral = true;
                            TInfo_TI ti;
                            if (!EnumClientServiceDictionary.TIHierarchyList.TryGetValue(description.IntegralTI_ID.Value, out ti) || ti == null)
                            {
                                continue;
                            }
                            hierarchyObject = ti;
                        }
                        else if (description.TP_ID.HasValue && tps != null)
                        {
                            TPoint tp;
                            if (!tps.TryGetValue(description.TP_ID.Value, out tp) || tp == null)
                            {
                                continue;
                            }
                            hierarchyObject = tp;
                        }
                        else if (!string.IsNullOrEmpty(description.Formula_UN) && EnumClientServiceDictionary.FormulasList != null)
                        {
                            var formula = EnumClientServiceDictionary.FormulasList[description.Formula_UN];
                            hierarchyObject = formula;
                        }
                        else if (!string.IsNullOrEmpty(description.OurFormula_UN))
                        {
                            TFormulaForSection formula;
                            if (!EnumClientServiceDictionary.FormulaFsk.TryGetValue(description.OurFormula_UN, out formula) || formula == null)
                            {
                                continue;
                            }
                            hierarchyObject = formula;
                        }
                        else if (!string.IsNullOrEmpty(description.ContrFormula_UN))
                        {
                            TFormulaForSection formula;
                            if (!EnumClientServiceDictionary.FormulaCA.TryGetValue(description.ContrFormula_UN, out formula) || formula == null)
                            {
                                continue;
                            }
                            hierarchyObject = formula;
                        }
                        else if (description.PTransformator_ID.HasValue)
                        {
                            var transformator = EnumClientServiceDictionary.GetOrAddTransformator(description.PTransformator_ID.Value, null);
                            hierarchyObject = transformator;
                        }
                        else if (description.PReactor_ID.HasValue)
                        {
                            var reactor = EnumClientServiceDictionary.GetOrAddReactor(description.PReactor_ID.Value, null);
                            hierarchyObject = reactor;
                        }
                        else if (description.Section_ID.HasValue)
                        {
                            var      hierarhicalSections = EnumClientServiceDictionary.GetSections();
                            TSection hierarhicalSection;
                            if (hierarhicalSections != null && hierarhicalSections.TryGetValue(description.Section_ID.Value, out hierarhicalSection))
                            {
                                hierarchyObject = hierarhicalSection;
                            }
                        }
                        else if (!string.IsNullOrEmpty(description.FormulaConstant_UN))
                        {
                            var formulaConstant = EnumClientServiceDictionary.FormulaConstantDictionary[description.FormulaConstant_UN];
                            hierarchyObject = formulaConstant;
                        }

                        if (hierarchyObject == null)
                        {
                            continue;
                        }

                        var itemRows = FindDescriptions(description, row, dispatcher);
                        if (itemRows != null)
                        {
                            itemRows.Add(new BalanceFreeHierarchyItemRow(hierarchyObject, description.ChannelType, description.Coef ?? 1, onFieldChanged,
                                                                         description.SortNumber, itemRows, isIntegral, (EnumDataSourceType?)description.DataSource_ID));
                        }

                        //Раскрываем дерево на первом объекте баланса
                        if (isFirstRow)
                        {
                            //fhTree.Dispatcher.BeginInvoke((Action)(() =>
                            //{
                            //    var freeHierTreeId = FormulaEditor_Frame.FindTreeByObjectType(hierarchyObject);
                            //    fhTree.ReloadTree(freeHierTreeId, hierarchyObject: hierarchyObject);
                            //}), DispatcherPriority.Background);

                            result = hierarchyObject;

                            isAdded    = true;
                            isFirstRow = false;
                        }
                    }
                }

                source.Add(row);
            }

            dispatcher.BeginInvoke((Action)(() => Source.AddRange(source)));

            //if (!isAdded)
            //{
            //    Task.Factory.StartNew(() =>
            //    {
            //        Thread.Sleep(100);
            //        //Раскрываем дерево на родителе баланса
            //        fhTree.Dispatcher.BeginInvoke((Action)(() =>
            //           fhTree.ExpandAndSelect(_hierarchyObject, true)), DispatcherPriority.ContextIdle);
            //    });
            //}

            return(result);
        }
        private Tuple <List <IDHierarchy>, string, CancellationToken> InvokeSearch(string text, string parentText, enumTypeHierarchy?typeHierarchy, CancellationToken token)
        {
            var needFindTI     = _descriptor.NeedFindTI;
            var needFindUaNode = _descriptor.NeedFindUaNode;
            var needFindTransformatorsAndreactors = _descriptor.NeedFindTransformatorsAndreactors; //Необходим поиск трансформаторов и реакторов по базе (т.к. еще не подгрузились)
            var freeHierTreeId        = _descriptor.Tree_ID ?? -101;
            var findUspdAndE422InTree = _descriptor.ShowUspdAndE422InTree;
            var tiComparer            = new IFreeHierarchyObjectComparerTyped();
            var objectComparer        = new HierarchyObjectFoundedComparer();
            var foundedObjects        = new ConcurrentStack <IDHierarchy>();

#if DEBUG
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Start();
#endif
            Parallel.Invoke(() =>
            {
                //if (_findTiType == EnumFindTiType.Pik) return;

                try
                {
                    //поиск прочих объектов
                    var hierObjects =
                        ARM_Service.TREE_FindHierObject(text, parentText, Manager.User.User_ID, freeHierTreeId, _findTiType.ToString(), findUspdAndE422InTree, typeHierarchy);
                    if (hierObjects != null && hierObjects.Count > 0)
                    {
                        foundedObjects.PushRange(hierObjects.OrderBy(h => h.TypeHierarchy).ThenByDescending(h => h, objectComparer).ToArray());
                    }
                }
                catch (Exception ex)
                {
                    Manager.UI.ShowMessage(ex.Message);
                }
            },
                            () =>
            {
                if (!needFindTransformatorsAndreactors)
                {
                    return;
                }

                try
                {
                    //Поиск трансформаторов и реакторов
                    var reactorsAndTransformators = ServiceFactory.ArmServiceInvokeSync <Tuple <List <Hard_PTransformator>, List <Hard_PReactors> > >("TREE_TransformatorOrReactor", text);
                    if (reactorsAndTransformators != null)
                    {
                        if (reactorsAndTransformators.Item1 != null)
                        {
                            reactorsAndTransformators.Item1.ForEach(transformator =>
                            {
                                foundedObjects.Push(
                                    EnumClientServiceDictionary.GetOrAddTransformator(transformator.PTransformator_ID,
                                                                                      transformator));
                            });
                        }

                        if (reactorsAndTransformators.Item2 != null)
                        {
                            reactorsAndTransformators.Item2.ForEach(reactor =>
                            {
                                foundedObjects.Push(
                                    EnumClientServiceDictionary.GetOrAddReactor(reactor.PReactor_ID, reactor));
                            });
                        }
                    }
                }
                catch (Exception ex)
                {
                    Manager.UI.ShowMessage(ex.Message);
                }
            },
                            () =>
            {
                //Поиск узлов OPC на дереве

                if (!needFindUaNode)
                {
                    return;
                }

                try
                {
                    var opcNodes = UAService.Service.UA_FindNode(text, freeHierTreeId, _findTiType == EnumFindTiType.MeterSerialNumber ? "UANode_ID" : null); // "UANode_ID"
                    if (opcNodes != null && opcNodes.Count > 0)
                    {
                        //Предварительная прогрузка узлов с типами найденных узлов (чтобы визуалка не тормозила)
                        UAHierarchyDictionaries.UANodesDict.Prepare(new HashSet <long>(opcNodes
                                                                                       .Where(fn => fn.Node.UATypeNode_ID.HasValue)
                                                                                       .Select(fn => fn.Node.UATypeNode_ID.Value)));

                        foundedObjects.PushRange(opcNodes.ToArray());
                    }
                }
                catch (Exception ex)
                {
                    Manager.UI.ShowMessage(ex.Message);
                }
            });

#if DEBUG
            sw.Stop();
            Console.WriteLine("Поиск {0} млс", sw.ElapsedMilliseconds);
#endif

            //Отмена поиска
            if (token.IsCancellationRequested)
            {
                return(null);
            }

            //Подготавливаем словари
            Task.Factory.StartNew(() => FreeHierarchyTreePreparer.PrepareGlobalDictionaries(foundedObjects, token: token));

            return(new Tuple <List <IDHierarchy>, string, CancellationToken>(foundedObjects.OrderByDescending(d => d.TypeHierarchy).ToList(), text, token));
        }