使用System.Timer和TreeView时访问UI线程



我有一个TreeView,其中一些节点具有包含IP地址的标记属性。

TreeView有一个ImageList,它包含3个条目,一个红色圆圈、一个绿色圆圈和一个橙色圆圈。

我想每x秒ping一次适当的IP地址(我目前有一个定时器,每分钟发送一个"脉冲"(,然后更新相关节点的ImageIndex以表示正确的输出(失败=红色等(。

在这个操作过程中,我一直在更新UI线程,我确信Timer是异步工作的,所以它不会和UI在同一个线程上。

我认为调用一个非异步的方法可以更新UI,但我得到了一个错误,即我在错误的线程上编辑UI。

下面是我在Timer的线程上运行的方法,它遍历每个列表并向每个IP发送一个ping请求。

private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
// Iterate through all root nodes
foreach(TreeNode tn in mainTree.Nodes)
{
// Iterate through all the children of the 'root' nodes
foreach(TreeNode child in tn.Nodes)
{
// Extract all nodes from these children
TreeNodeCollection myNodes = ((TreeNode)child).Nodes;
// Create ping object
System.Net.NetworkInformation.Ping pinger = new();
PingReply pingReply;
// Iterate through each of the nodes, send a ping request and then update the UI based on the result of the ping
foreach(TreeNode node in myNodes)
{
if(node.Tag != null)
{
pingReply = pinger.Send(node.Tag.ToString());
if (pingReply.Status.ToString().Contains("Success"))
{
UpdateUI(node, 0); // If successful, set the image index to show green 
} 
else if (pingReply.Status.ToString().Contains("Failed"))
{
UpdateUI(node, 1);
}
}
}
}

}
}

我如何尝试更新UI:

public static void UpdateUI(TreeNode node, int image) // int image = the index of the image 0 = green, 1 = red, 2 = orange for UI elements
{
node.ImageIndex = image;
}

计时器:

private void StartTimer()
{
aTimer = new System.Timers.Timer(60000); // Set interval to every minute
aTimer.Elapsed += OnTimedEvent;
aTimer.AutoReset = true;
aTimer.Enabled = true;
}

初始化计时器:

public Form1()
{
InitializeComponent();
StartTimer();
// Instantiate TreeViewSerializer class for persistence
TreeViewSerializer tvS = new TreeViewSerializer();
// Deserealize tree view for persistence
tvS.DeserializeTreeView(mainTree, xmlFile);
mainTree.ImageList = imageList1;
mainTree.ExpandAll();
}

如何访问UI线程以便能够使用从成功/失败的ping返回的值更新UI?

尝试更改您的方法:

public static void UpdateUI(TreeNode node, int image) // int image = the index of the image 0 = green, 1 = red, 2 = orange for UI elements
{
node.ImageIndex = image;
}

至:

public static void UpdateUI(TreeNode node, int image) // int image = the index of the image 0 = green, 1 = red, 2 = orange for UI elements
{
this.Invoke(new Action(() =>
{
node.ImageIndex = image;
}));
}

最新更新