对于10 IPS来说没有问题。但是,当我尝试ping 200 Ips时,它将使UI滞后5秒钟,并且CPU使用率变得很高。还有其他方法吗?
Dim obj As New Object
Dim list As New List(Of String)
For Each item As ListViewItem In ListView1.Items
Dim T As New Thread(Sub()
Thread.Sleep(10)
Dim p As Ping
Dim reply As PingReply
p = New Ping
reply = p.Send(item.Text)
SyncLock obj
list.Add(reply.RoundtripTime.ToString)
End SyncLock
End Sub)
T.Start()
Next
答案 0 :(得分:0)
您无法在线程代码内访问item
。首先,它是一个UI元素,从非UI线程访问UI元素是不好的。其次,在第一个线程开始之前,循环将遍历许多(如果不是全部)元素,这意味着线程内部的item
将在线程开始之前发生变化。
您也不会处置Ping
对象。那是内存泄漏。
为此,最好使用Microsoft的Reactive Framework。它使这个超级容易。只需这样做:
Dim subscription As IDisposable =
ListView1 _
.Items _
.Cast(Of ListViewItem) _
.Select(Function (lvi) lvi.Text) _
.ToObservable() _
.SelectMany(Function (t) Observable.Using( _
Function () New Ping(), _
Function (p) Observable.Start(Function () p.Send(t).RoundtripTime.ToString()))) _
.ToList() _
.ObserveOn(ListView1) _
.Subscribe( _
Sub (list)
' Do something with your list here
End Sub)
在任何线程发生之前,这可以正确访问UI元素。它处理您的Ping
实例。它编组回UI线程。最后,它会根据需要在.Subscribe
方法中返回您的列表。
只需NuGet System.Reactive.Windows.Forms
,然后将Imports System.Reactive
添加到您的代码中即可。