我有简单的WindowsForm应用程序,它包含TreeView。初始化时 - TreeView使用默认的imageIndexes从XML构建。我的TreeView由服务器名称组成。在Tag元素中,我放置了由主机和IP组成的Dictionary。初始化后我调用方法,如果服务器是timedOut,则更改imageIndex。我需要在BackgroundWorker中调用此方法,即非阻塞主线程(GUI)。我计划每分钟运行一次这个方法。以下是这种方法:
private void checkServersTree()
{
TreeNodeCollection rootNodes = treeViewSrv.Nodes;
TreeNodeCollection childNodes;
PingServers ps = new PingServers();
for (int i = 0; i < rootNodes.Count; i++)
{
childNodes = treeViewSrv.Nodes[i].Nodes;
treeViewSrv.Nodes[i].Text += string.Format(" ({0})", childNodes.Count);
int downServers = 0;
foreach (TreeNode tNode in childNodes)
{
if (tNode.Tag != null)
{
Dictionary<string, string> dicParams = tNode.Tag as Dictionary<string, string>;
if (!ps.getServerStatus(dicParams["host"], dicParams["ip"]))
{
tNode.ImageIndex = 1; //red
rootNodes[i].ImageIndex = 2; //yellow
downServers++;
}
}
}
if(downServers == childNodes.Count)
rootNodes[i].ImageIndex = 4; //fatal red
}
}
提前致谢!
谢谢你的回答! 在我写这篇文章之前,我读了一下Invoke和BeginInvoke。但我无法解决这个问题 - 运行更改TreeView ImageIndexes的异步线程。我去了你的链接并编写了代码(如下),但GUI保持阻止状态。我做错了什么?
namespace CCCServers
{
public partial class CCCServers : Form
{
public delegate void checkSrvDelegate();
public checkSrvDelegate myDelegate;
private Thread myThread;
public CCCServers()
{
InitializeComponent();
TreeFromXML tfXML = new TreeFromXML(treeViewSrv, "../../Servers.xml");
tfXML.initTreeNodesFromXML();
treeViewSrv.ExpandAll();
//checkServersTree();
myDelegate = new checkSrvDelegate(checkServersTree);
}
private void checkServersTree()
{
TreeNodeCollection rootNodes = treeViewSrv.Nodes;
TreeNodeCollection childNodes;
PingServers ps = new PingServers();
for (int i = 0; i < rootNodes.Count; i++)
{
childNodes = treeViewSrv.Nodes[i].Nodes;
treeViewSrv.Nodes[i].Text += string.Format(" ({0})", childNodes.Count);
int downServers = 0;
foreach (TreeNode tNode in childNodes)
{
if (tNode.Tag != null)
{
Dictionary<string, string> dicParams = tNode.Tag as Dictionary<string, string>;
if (!ps.getServerStatus(dicParams["host"], dicParams["ip"]))
{
tNode.ImageIndex = 1; //red
rootNodes[i].ImageIndex = 2; //yellow
downServers++;
}
}
}
if(downServers == childNodes.Count)
rootNodes[i].ImageIndex = 4; //fatal red
}
}
private void btnRDP_Click(object sender, EventArgs e)
{
myThread = new Thread(new ThreadStart(threadFunction));
myThread.Start();
}
private void threadFunction()
{
MyThreadClass myThreadClassObject = new MyThreadClass(this);
myThreadClassObject.Run();
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
MessageBox.Show(e.Node.Text, "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void treeViewSrv_AfterSelect(object sender, TreeViewEventArgs e)
{
e.Node.SelectedImageIndex = e.Node.ImageIndex; //Что бы иконка не менялась при выборе узла
}
}
//***************************************************************************
public class MyThreadClass
{
CCCServers cccSrv;
public MyThreadClass(CCCServers myForm)
{
cccSrv = myForm;
}
public void Run()
{
cccSrv.Invoke(cccSrv.myDelegate);
}
}
}
答案 0 :(得分:0)
您需要使用表单的Invoke方法在创建窗口句柄的线程上执行用户界面方法。 E.g。
Invoke((Action) checkServersTree);
答案 1 :(得分:0)
我解决了我的问题。在特殊位置插入我的代码之后Debug.WriteLine(String.Format("<<<<<<<< This is {0} thread", Thread.CurrentThread.ManagedThreadId));
我意识到在主线程中调用了Control.Invoke
,因此所有花时间认识不到Control.Invoke
的人。请参阅以下代码:
private delegate void setServersCountDelegate(int idx, int cnt);
private delegate void setChldNodeImgIndexDelegate(TreeNode tNode, int imgIdx);
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
testBuildTree();
}
private void testBuildTree()
{
Thread.CurrentThread.Name = "CheckServers";
Debug.WriteLine(String.Format("|||||||||| This is {0} thread", Thread.CurrentThread.ManagedThreadId));
changeImgIndex();
}
private void changeImgIndex()
{
Debug.WriteLine(String.Format("--------- This is {0} thread", Thread.CurrentThread.ManagedThreadId));
TreeNodeCollection rootNodes = treeViewSrv.Nodes;
TreeNodeCollection childNodes;
for (int i = 0; i < rootNodes.Count; i++)
{
childNodes = treeViewSrv.Nodes[i].Nodes;
//treeViewSrv.Nodes[i].Text += string.Format(" ({0})", childNodes.Count);
treeViewSrv.Invoke(new setServersCountDelegate(setServersCount), new object[] { i, childNodes.Count });
int downServers = 0;
foreach (TreeNode tNode in childNodes)
{
if (tNode.Tag != null)
{
Dictionary<string, string> dicParams = tNode.Tag as Dictionary<string, string>;
if (!getServerStatus(dicParams["host"], dicParams["ip"]))
{
Debug.WriteLine(String.Format("<<<<<<<< This is {0} thread", Thread.CurrentThread.ManagedThreadId));
//tNode.ImageIndex = 1; //red
treeViewSrv.Invoke(new setChldNodeImgIndexDelegate(setChldNodeImgIndex), new object[] { tNode, 1 }); //red
//rootNodes[i].ImageIndex = 2; //yellow
treeViewSrv.Invoke(new setChldNodeImgIndexDelegate(setChldNodeImgIndex), new object[] { rootNodes[i], 2 }); //yellow
downServers++;
}
}
}
if (downServers == childNodes.Count)
{
//rootNodes[i].ImageIndex = 4; //fatal red
treeViewSrv.Invoke(new setChldNodeImgIndexDelegate(setChldNodeImgIndex), new object[] { rootNodes[i], 4 });
}
}
}
private void setServersCount(int idx, int cnt)
{
string[] spltNodeText = treeViewSrv.Nodes[idx].Text.Split(' ');
treeViewSrv.Nodes[idx].Text = string.Format("{0} ({1})", spltNodeText[0], cnt);
}
private void setChldNodeImgIndex(TreeNode tNode, int imgIdx)
{
tNode.ImageIndex = imgIdx;
}