本文介绍了Ping 网络上的多个设备名称(主机名)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

pc1电脑2打印3电脑5打印....

这样的名字有500多个.
我知道如何 ping 他们:

For i = 0 To DataGridView1.Rows.Count - 1尝试如果 My.Computer.Network.Ping(DataGridView1.Item(0, i).Value) = True 那么DataGridView1.Rows(i).DefaultCellStyle.BackColor = Color.Lime别的DataGridView1.Rows(i).DefaultCellStyle.BackColor = Color.Red万一Catch ex 作为例外DataGridView1.Rows(i).DefaultCellStyle.BackColor = Color.Red结束尝试下一个

问题是Ping时间很长,应用卡死.
你怎样才能加快这个过程?
假设该节点不可用,则只需将其从列表中删除即可.

解决方案

同时 Ping 多个地址的示例,使用


假设您从 Button.Click 处理程序开始 ping 序列.
请注意,处理程序声明为 async.

私有异步子 btnMassPing_Click(sender As Object, e As EventArgs) 处理 btnMassPing.Click等待 MassPing(DataGridView1, 1, 2)结束子

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

导入 System.Drawing导入 System.Net.NetworkInformation导入 System.Net.Sockets导入 System.Threading.Tasks私有异步函数 MassPing(dgv As DataGridView, statusColumn As Integer, addressColumn As Integer) 作为任务Dim obj = 新对象()Dim 任务 = 新列表(任务)()Dim progress = New Progress(Of (sequence As Integer, reply As Object))(子(报告)同步锁对象昏暗状态 = IPStatus.Unknown如果 TypeOf report.reply 是 PingReply 那么status = DirectCast(report.reply, PingReply).StatusElseIf TypeOf report.reply 是 SocketError ThenDim socErr = DirectCast(report.reply, SocketError)status = If(socErr = SocketError.HostNotFound,IPStatus.DestinationHostUnreachable,IPStatus.Unknown)万一Dim color As Color = If(status = IPStatus.Success, Color.Green, Color.Red)暗单元格 = dgv(statusColumn, report.sequence)cell.Style.BackColor = 颜色cell.Value = If(status = IPStatus.Success, 在线", status.ToString())结束同步锁结束子)对于 row As Integer = 0 To dgv.Rows.Count - 1如果 row = dgv.NewRowIndex 然后继续 ForDim ipAddr = dgv(addressColumn, row).Value.ToString()任务.添加(PingAsync(ipAddr,5000,行,进度))下一个尝试等待 Task.WhenAll(tasks)Catch ex 作为例外' 记录/报告异常Console.WriteLine(ex.Message)结束尝试结束函数

PingAsync 工作者方法:

私有异步函数 PingAsync(ipAddress As String, timeOut As Integer, sequence As Integer, progress As IProgress(Of (seq As Integer, reply As Object))) As TaskDim 缓冲区 As Byte() = New Byte(32) {}Dim ping = 新 Ping()尝试Dim options = New PingOptions(64, True)Dim 回复 = 等待 ping.SendPingAsync(ipAddress, timeOut, buffer, options)进度.报告((序列,回复))将 pex 捕获为 PingException如果 TypeOf pex.InnerException 是 SocketException 那么Dim socEx = DirectCast(pex.InnerException, SocketException)progress.Report((sequence, socEx.SocketErrorCode))万一最后ping.Dispose()结束尝试结束函数

A DataGridView displays hostnames at Column index 0, computer / printer names on the network.

pc1
pc2
print3
pc5
print
....

There are more than 500 such names.
I know how to ping them:

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

The problem is that the Ping takes a very long time and the application freezes.
How can you speed up this procedure?
And let's say if the node is not available, then simply remove it from the list.

解决方案

An example to Ping multiple addresses at the same time, using the async version of provided y the Ping class, Ping.SendPingAsync().
This version is await-able, not the same as the Ping.SendAsync() method, still asynchronous by event-driven.

Since you're using a DataGridView to both store the Ip/Host addresses and to present the PingReply results, you need to determine a way to match the Ping result to correct Cell of the DataGridView from which the Ip/Host address was taken.
Here, I'm passing to the method the Row's Index, so when the Ping result comes back, asynchronously, we can match the response to a specific Cell in the DataGridView.

To make the initialization method more generic, I'm passing also the index of the Column where the Ip/Host address is stored and the index of the Column that will show the result (you could also just pass all indexes, not a DataGridView Control reference to the method and handle the results in a different way).

A loop extracts the addresses from the the DataGridView and creates a List(Of Task), adding a PingAsync() Task for each address found.
When the collection is completed, the List(Of Task) is passed to the Task.WhenAll() method, which is then awaited.
This method starts all the Task in the list and returns when all Task have a result.

► Note that the Ping procedure sets a TimeOut, to 5000ms here, so all the Ping Tasks will return before or within that interval, successful or not.
You can the decide if you want to reschedule the failed Pings or not.

The UI update is handled using a Progress delegate. It's just a method (a callback) that is called when the Ping procedure has a result to show.
It can also be used when the method that updates the UI runs in a different Thread: the Report() method will call the Progress object delegate in the Thread that created the delegate: the UI Thread, here (in the example, we're not actually ever leaving it, though).

This is how it works:


Assume you're starting the ping sequence from Button.Click handler.
Note that the handler is declared async.

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

Initialization method and IProgress<T> report handler:

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 worker method:

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

这篇关于Ping 网络上的多个设备名称(主机名)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 20:48