【问题标题】:Change foreground color of TreeView node from a seperated Thread从单独的线程更改 TreeView 节点的前景色
【发布时间】:2017-06-11 11:54:56
【问题描述】:

使用下面的代码,我在 MainForm LoadEvent 中用一个根节点和几个子节点填充 Treeview。使用按钮 btnPing 我遍历节点并搜索级别 2 的子节点。然后使用 My.computer.network.ping 查询这些节点,并且 ChildNode 的 ForeColor 根据结果红色或绿色着色。整部作品是同义词。然而,图形用户界面每次都让我冻结。

    '### TreeView Test
Option Explicit On
Option Strict On
Public Partial Class MainForm
    Public Sub New()
        Me.InitializeComponent()
    End Sub

'### Hauptprogramm wird geladen ###
    Sub MainFormLoad(sender As Object, e As EventArgs)
'Treeview befüllen
With treeView1
.Nodes.Add("Test1")
.Nodes(0).Nodes.Add("Test1_a")
.Nodes(0).Nodes.Add("Test1_b")
.Nodes(0).Nodes.Add("Test1_c")
.Nodes(0).Nodes(0).Nodes.Add("10.23.59.1")
.Nodes(0).Nodes(1).Nodes.Add("10.23.59.90")
.Nodes(0).Nodes(1).Nodes.Add("10.23.59.90")
.Nodes(0).Nodes(2).Nodes.Add("10.23.59.10")
.Nodes(0).Nodes(2).Nodes.Add("10.23.59.11")
.Nodes(0).Nodes(2).Nodes.Add("10.23.59.12")
.Nodes(0).Nodes(2).Nodes.Add("10.23.59.13")
.Nodes(0).Nodes(2).Nodes.Add("10.23.59.14")
End With
'Treeview aufklappen
treeView1.ExpandAll
End Sub

'### Sub zum rekursiven durchsuchen der Nodes ###
    Private Sub RecurseNodes(ByVal col As TreeNodeCollection)
        For Each tn As TreeNode In col             
        If tn.Level = 2 Then
            Try
            If My.Computer.Network.Ping(tn.Text) Then
                tn.ForeColor = Color.Green
                tn.StateImageIndex= 4
            Else    
                tn.ForeColor = Color.Red
                tn.StateImageIndex=5
            End If
            Catch ex As Exception
                tn.ForeColor = Color.Red
                tn.StateImageIndex=5
            End Try
        End If

        If tn.Nodes.Count > 0 Then
            RecurseNodes(tn.Nodes)
        End If
        Next tn
    End Sub

'### Button zum starten der rekursiven Suche ###
    Sub BtnPingClick(sender As Object, e As EventArgs)
        'Treeview rekursiv durchsuchen
        RecurseNodes(treeView1.Nodes)
    End Sub
End Class

现在我想转换整体,以便 Ping 在单独的线程中运行。现在我对这个过程只有一个理解问题。我可以用参数传输启动一个线程吗?然后我将遍历列表并从具有 2 级线程的每个节点开始并等待反馈。最好的方法是什么?

最好的问候 凯

【问题讨论】:

标签: vb.net multithreading treeview


【解决方案1】:

这是另一种方法:

Sub BtnPingClick(sender As Object, e As EventArgs)
    'Treeview rekursiv durchsuchen
    RecurseNodes(TreeView1.Nodes)
End Sub

Private Async Sub RecurseNodes(ByVal col As TreeNodeCollection)
    For Each tn As TreeNode In col
        If tn.Level = 2 Then
            Dim T As Task(Of Boolean) = Ping(tn.Text)
            Await T
            tn.ForeColor = If(T.Result, Color.Green, Color.Red)
            tn.StateImageIndex = If(T.Result, 4, 5)
        ElseIf tn.Nodes.Count > 0 Then
            RecurseNodes(tn.Nodes)
        End If
    Next tn
End Sub

Private Function Ping(ByVal ip As String) As Task(Of Boolean)
    Return Task.Factory.StartNew(Of Boolean)(
        Function() As Boolean
            Try
                Return My.Computer.Network.Ping(ip)
            Catch ex As Exception
                Return False
            End Try
        End Function)
End Function

【讨论】:

  • 您正在尝试从一个不起作用的任务访问 UI。
  • 在哪里?...我没有从任务访问 UI。请详细说明@dbasnett
  • 在 Using 块中。
  • 当我们到达这些行时,我们已经从任务返回(并且回到了 UI 线程)。 @dbasnett
  • 我确实尝试过代码;它工作正常,没有错误,我的 UI 响应迅速。更改了代码以使其更清楚正在发生的事情。 @dbasnett
【解决方案2】:

一些想法...

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim t As Task = Task.Run(Sub()
                                 RecurseNodes(TreeView1.Nodes(0))
                             End Sub)
End Sub

Private Sub RecurseNodes(ByVal col As TreeNode)
    For Each tn As TreeNode In col.Nodes
        If tn.Level < 2 AndAlso tn.Nodes.Count > 0 Then
            RecurseNodes(tn)
        ElseIf tn.Level = 2 Then
            Dim tp As Task
            tp = Task.Run(Sub()
                              Dim c As Color
                              Dim idx As Integer
                              Try
                                  If My.Computer.Network.Ping(tn.Text) Then
                                      c = Color.Green
                                      idx = 4
                                  Else
                                      c = Color.Red
                                      idx = 5
                                  End If
                              Catch ex As Exception
                                  c = Color.Red
                                  idx = 5
                              End Try
                              Me.Invoke(Sub()
                                            tn.ForeColor = c
                                            tn.StateImageIndex = idx
                                        End Sub)
                          End Sub)
        End If
    Next tn
End Sub

【讨论】:

  • 谢谢,但我收到 3 个错误:任务未定义。你能帮我解决这个问题吗?
  • @Kay 你使用的是什么版本的 .Net?
  • .net 4 我正在使用
  • @Kay 在代码开头添加这个 Imports System.Threading.Tasks
猜你喜欢
  • 1970-01-01
  • 2019-12-29
  • 2012-10-04
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多