winforms Ping网络上的多个设备名称(主机名)

643ylb08  于 2023-04-12  发布在  其他
关注(0)|答案(1)|浏览(128)

DataGridView显示列索引0处的主机名、网络上的计算机/打印机名称。

pc1
pc2
print3
pc5
print
....

有500多个这样的名字。
我知道怎么联系他们

For i = 0 To DataGridView1.Rows.Count - 1
    Try
        If My.Computer.Network.Ping(DataGridView1.Item(0, i).Value) = True Then
            DataGridView1.Rows(i).DefaultCellStyle.BackColor = Color.Lime
        Else
            DataGridView1.Rows(i).DefaultCellStyle.BackColor = Color.Red
        End If
    Catch ex As Exception
        DataGridView1.Rows(i).DefaultCellStyle.BackColor = Color.Red
    End Try
Next

问题是Ping需要很长时间,应用程序会冻结。
如何加快这一进程?
假设该节点不可用,则只需将其从列表中删除即可。

hc2pp10m

hc2pp10m1#

使用PingPing.SendPingAsync()提供的异步版本同时Ping多个地址的示例。
这个版本是可等待的,与Ping.SendAsync()方法不同,仍然是 * 异步 * 的,但是是事件驱动的。
由于您使用DataGridView来存储IpAddress/HostName并显示PingReply结果,因此需要确定一种方法来匹配Ping结果,以纠正获取Ip/Host地址的DataGridView的Cell。
在这里,我将Row的Index传递给方法,因此当Ping结果异步返回时,我们可以将响应与DataGridView中的特定Cell相匹配。
为了使 initialization 方法更通用,我还传递了存储Ip/Host地址的Column的索引和将显示结果的Column的索引(您也可以只传递所有索引,而不是DataGridView Control引用到该方法并以不同的方式处理结果)。
一个循环从DataGridView中提取地址并创建一个**List(Of Task)**,为找到的每个地址添加一个PingAsync()任务。
当收集完成时,List(Of Task)被传递给Task.WhenAll()方法,然后等待该方法。
此方法启动列表中的所有Task,并在所有Task都有结果时返回。
►请注意,Ping过程将TimeOut设置为5000ms,因此所有任务都将在该时间间隔之前或之内返回,无论成功与否。
然后,您可以决定是否要重新安排失败的Ping。
UI更新是使用Progress委托处理的。它只是一个方法(Action委托),当Ping过程有结果要显示时调用。
当更新UI的方法在不同的线程中运行时,也可以使用它:Report()方法将调用创建委托的线程中的Progress对象委托:UI线程,在这里(在示例中,我们实际上并没有离开它)。
它是这样工作的:

假设您从Button.Click事件处理程序启动ping序列。
注意,处理程序被声明为async

Private Async Sub btnMassPing_Click(sender As Object, e As EventArgs) Handles btnMassPing.Click
    Await MassPing(DataGridView1, 1, 2)
End Sub

初始化方法和IProgress<T>报告处理程序:

Imports System.Drawing
Imports System.Net.NetworkInformation
Imports System.Net.Sockets
Imports System.Threading.Tasks

Private Async Function MassPing(dgv As DataGridView, statusColumn As Integer, addressColumn As Integer) As Task
    Dim obj = New Object()
    Dim tasks = New List(Of Task)()

    Dim progress = New Progress(Of (sequence As Integer, reply As Object))(
            Sub(report)
                SyncLock obj
                    Dim status = IPStatus.Unknown
                    If TypeOf report.reply Is PingReply Then
                        status = DirectCast(report.reply, PingReply).Status
                    ElseIf TypeOf report.reply Is SocketError Then
                        Dim socErr = DirectCast(report.reply, SocketError)
                        status = If(socErr = SocketError.HostNotFound,
                            IPStatus.DestinationHostUnreachable,
                            IPStatus.Unknown)
                    End If

                    Dim color As Color = If(status = IPStatus.Success, Color.Green, Color.Red)
                    Dim cell = dgv(statusColumn, report.sequence)
                    cell.Style.BackColor = color
                    cell.Value = If(status = IPStatus.Success, "Online", status.ToString())
                End SyncLock
            End Sub)

    For row As Integer = 0 To dgv.Rows.Count - 1
        If row = dgv.NewRowIndex Then Continue For
        Dim ipAddr = dgv(addressColumn, row).Value.ToString()
        tasks.Add(PingAsync(ipAddr, 5000, row, progress))
    Next

    Try
        Await Task.WhenAll(tasks)
    Catch ex As Exception
        ' Log / report the exception
        Console.WriteLine(ex.Message)
    End Try
End Function

PingAsync工作方法:

Private Async Function PingAsync(ipAddress As String, timeOut As Integer, sequence As Integer, progress As IProgress(Of (seq As Integer, reply As Object))) As Task
    Dim buffer As Byte() = New Byte(32) {}
    Dim ping = New Ping()

    Try
        Dim options = New PingOptions(64, True)
        Dim reply = Await ping.SendPingAsync(ipAddress, timeOut, buffer, options)
        progress.Report((sequence, reply))
    Catch pex As PingException
        If TypeOf pex.InnerException Is SocketException Then
            Dim socEx = DirectCast(pex.InnerException, SocketException)
            progress.Report((sequence, socEx.SocketErrorCode))
        End If
    Finally
        ping.Dispose()
    End Try
End Function

相关问题