问题描述
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 网络上的多个设备名称(主机名)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!