男孩,如果你找不到可靠的来源,那么学习新东西可能会非常令人头痛。我一直在以线性方式设计应用程序已有一段时间了,并希望采用更强大的方法。我一直在阅读线程,也许已经达到了比我应该更大的水平。但是,当应用程序需要它时,通常会逐步升级,并且没有比现在更好的时间来学习新的东西。
我的程序旨在做一些看似相当简单的事情,但在平稳的跑步庄园中创造起来非常困难。原始设计创建了它希望ping的网络上每个设备的对象,在我的真实世界环境中它们是Kindles。目标是通过Pining他们确保他们仍然连接到网络。我使用For Loop
和Obj Array
在Timer
上执行此设置。这会产生意外结果,导致ListView
在ListView1.Items.Clear
之后闪烁并缓慢加载。我进化为更新List Items
而不是清除它们,闪烁仍然存在。
我认为这是由于数组和ping的过程缓慢,所以我开始寻找解决方案并遇到Multi-Threading
。我已经知道了一段时间,但尚未深入研究这种做法。我的程序似乎需要更快的速度和更平稳的操作,所以我抓了它。完整形式的下面的代码是结果,但它崩溃并抛出错误。很明显,我并没有按照预期使用线程。在更简单的功能中使用它工作正常,我觉得我有把握。那就是如果我希望我的程序毫无意义地运行计数器。
我不知道在完成这项任务的步骤中接下来要做什么,并且我想把几种不同的方法组合成一个死的程序。我真的可以使用一些帮助重新回到正轨。欢迎所有评论,并感谢您查看我的代码。
Form1代码
Public Class Form1
'Obj Array
Public Shared objDevice As New List(Of kDevice)
'Thread Array for each Obj
Public Shared thread() As System.Threading.Thread
Private Sub ipRefresh(objID, itemPos)
Dim objDev As kDevice = objID
If My.Computer.Network.Ping(objDev.kIP) Then
objDev.kStatus = "Online"
objDev.kPings = 0
Else
objDev.kPings += 1
End If
If objDev.kPings >= 8 Then
objDev.kStatus = "Offline"
objDev.kPings = 0
ListView1.Items(itemPos).BackColor = Color.Red
End If
Dim str(4) As String
Dim itm As ListViewItem
str(0) = objDev.kName
str(1) = objDev.kIP
str(2) = objDev.kStatus
str(3) = objDev.kPings
itm = New ListViewItem(str)
ListView1.Items(itemPos) = itm
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.CheckForIllegalCrossThreadCalls = False
' Adding ListView Columns
ListView1.Columns.Add("Device", 100, HorizontalAlignment.Left)
ListView1.Columns.Add("IP Address", 150, HorizontalAlignment.Left)
ListView1.Columns.Add("Status", 60, HorizontalAlignment.Left)
ListView1.Columns.Add("Pings", 60, HorizontalAlignment.Left)
Dim ipList As New List(Of String)
Dim nameList As New List(Of String)
Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("kDevices.csv")
MyReader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
MyReader.Delimiters = New String() {","}
Dim currentRow As String()
Dim rowP As Integer = 1
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
Dim cellP As Integer = 0
Dim nTemp As String = ""
For Each currentField As String In currentRow
Select Case cellP
Case 0
nameList.Add(currentField.Replace("""", ""))
Case 1
ipList.Add(currentField.Replace("""", ""))
End Select
cellP += 1
Next
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & " is invalid. Skipping")
End Try
rowP += 1
End While
End Using
Dim nameLAR As String() = nameList.ToArray
Dim ipLAR As String() = ipList.ToArray
ReDim Preserve thread(nameLAR.Length)
For i As Integer = 0 To nameLAR.Length - 1
Dim newDevice As New kDevice
Dim objNum = i
objDevice.Add(newDevice)
newDevice.kName = nameLAR(i)
newDevice.kIP = ipLAR(i)
If My.Computer.Network.Ping(newDevice.kIP) Then
newDevice.kStatus = "Online"
Else
newDevice.kStatus = "Loading"
End If
Dim str(4) As String
Dim itm As ListViewItem
str(0) = newDevice.kName
str(1) = newDevice.kIP
str(2) = newDevice.kStatus
str(3) = newDevice.kPings
itm = New ListViewItem(str)
If newDevice.kStatus = "Loading" Then
itm.BackColor = Color.Yellow
End If
ListView1.Items.Add(itm)
thread(objNum) = New System.Threading.Thread(Sub() Me.ipRefresh(objDevice(objNum), objNum))
Next
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
For i As Integer = 0 To objDevice.Count - 1
thread(i).Start()
Next
End Sub
End Class
kDevice Class
Public Class kDevice
Private strkName As String
Private strkIP As String
Private strkStatus As String
Private strkLastStatus As String
Private strkPings As Integer = 0
Public Property kName As String
Get
Return strkName
End Get
Set(value As String)
strkName = value
End Set
End Property
Public Property kIP As String
Get
Return strkIP
End Get
Set(value As String)
strkIP = value
End Set
End Property
Public Property kStatus As String
Get
Return strkStatus
End Get
Set(value As String)
strkStatus = value
End Set
End Property
Public Property kPings As Integer
Get
Return strkPings
End Get
Set(value As Integer)
strkPings = value
End Set
End Property
End Class
我的代码第32行的错误/崩溃,当它试图将更新传递给ListView项时
An unhandled exception of type 'System.ArgumentException'
occurred in Microsoft.VisualBasic.dll
Additional information: InvalidArgument=Value of '18'
is not valid for 'index'.
或
An unhandled exception of type 'System.NullReferenceException'
occurred in Microsoft.VisualBasic.dll
Additional information: Object reference not set to an instance
of an object.
如果我的代码没有意义,或者至少知道我想要做什么,请告诉我,我会解释哪些部分不清楚。再次感谢您查看我的问题。
答案 0 :(得分:1)
我注意到一个可能的问题:
Dim str(4) As String
Dim itm As ListViewItem
str(0) = newDevice.kName
str(1) = newDevice.kIP
str(2) = newDevice.kStatus
str(3) = newDevice.kPings
itm = New ListViewItem(str)
If newDevice.kStatus = "Loading" Then
itm.BackColor = Color.Yellow
End If
ListView1.Items.Add(itm)
在这里,你声明str(4)将是5个可能的索引(记住它从零开始),你应该有4(str(3))。我不认为这是整个问题,但只是一点点你应该修复。您也可能希望在不设置
的情况下查看更新列表视图的其他方法Me.CheckForIllegalCrossThreadCalls = False
这是一个很棒的指南,在我完成第一个多线程应用程序时帮助了我:http://checktechno.blogspot.com/2012/11/multi-thread-for-newbies.html