Я решил эту проблему.
Для начала запустил метод в новом потоке:
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);
}
Работает медленно, но работает :)