Ответы пользователя по тегу .NET
  • Как обновить TreeView в реальном времени данными из другого потока?

    @AngryGrey Автор вопроса
    Инженер АСУТП
    Я решил эту проблему.
    Для начала запустил метод в новом потоке:

    private void FrOpcBrowser_Shown(object sender, EventArgs e)
            {
                try
                {
                    currentServer.Connect(serverID);
                    Text = serverID;
                    treeView1.Nodes.Clear();
                    treeView1.Nodes.Add(new TreeNode(serverID));
                    treeView1.SelectedNode = treeView1.Nodes[0];
                    TreeNode startNode = treeView1.SelectedNode;
                    Thread thread = new Thread(delegate () { DoBrowse(startNode, -1); });
                    thread.Start();
                }
                catch(Exception)
                {
                    MessageBox.Show("Oops");
                    Close();
                }
            }


    Затем, когда метод DoBrowse проверит все условия, то запускается метод RecureBrowse

    private void DoBrowse(TreeNode startNode, int depth)
            {
                try
                {
                    OPCNAMESPACETYPE opcOrgi = currentServer.QueryOrganization();
    
                    if (opcOrgi == OPCNAMESPACETYPE.OPC_NS_HIERARCHIAL)
                    {
                        //Устанавливем курсор на корневой узел дерева сервера
                        currentServer.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_TO, "");
                        //Проверяем не является ли выбранный узел корнем сервера
                        if (startNode.FullPath.Length > serverID.Length)
                        {
                            //Если выбранный узел не корень сервера, то получаем полный путь для данного узла
                            string[] splitpath = startNode.FullPath.Substring(serverID.Length + 1).Split(new char[] { '\t', '\\' });
                            //Имея полный путь, спускаемся до выбранного узла на сервере
                            foreach (string n in splitpath)
                            {
                                currentServer.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_DOWN, n);
                            }
                        }
                        RecurBrowse(startNode, depth);
                    }
                }
                catch(Exception)
                {
                    MessageBox.Show("browse error!", "DoBrowse", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                return;
            }
    
            private bool RecurBrowse(TreeNode startNode, int depth)
            {
                try
                {
                    if (depth == 0)
                    {
                        return true;
                    }
                    currentServer.Browse(OPCBROWSETYPE.OPC_BRANCH, out ArrayList lst);
                    if (lst == null || lst.Count < 1)
                    {
                        return true;
                    }
    
                    foreach(string branch in lst)
                    {
                        TreeNode nextNode = new TreeNode(branch);
                        AddNode(startNode, nextNode);
                        currentServer.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_DOWN, branch);
                        RecurBrowse(nextNode, depth - 1);
                        currentServer.ChangeBrowsePosition(OPCBROWSEDIRECTION.OPC_BROWSE_UP, "");
                        
                    }
                }
                catch(Exception)
                {
                    MessageBox.Show(this, "browse error!", "RecurBrowse", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return false;
                }
                return true;
            }


    В методе RecureBrowse добавление новой ноды происход вызовом метода AddNode, который вызывается (как я понял) в том потоке, которому принадлежит родительская нода.

    private void AddNode(TreeNode parentNode, TreeNode childNode)
            {
                if (InvokeRequired)
                {
                    Invoke(new Action<TreeNode, TreeNode>(AddNode), new TreeNode[] { parentNode, childNode });
                    return;
                }
                parentNode.Nodes.Add(childNode);
            }


    Работает медленно, но работает :)
    Ответ написан
    Комментировать