首先发布在这里。虽然很长时间潜伏着。我会做对的。
我的小方案项目是一个应用程序,它将从craigslist中删除帖子。一旦被抓取,列表数据就会被发送到" Form1"中的列表框。我创建了一个工人类来处理所有的抓取。我的班级功能" guiAdd()"将无法正确填充列表框。
鉴于Form1确实存在,它确实有一个名为" lvsearch"的列表框控件:
这就是我认为的问题: Class子程序
Private Sub guiAdd(ByVal data As String)
If Form1.lvsearch.InvokeRequired Then
Form1.lvsearch.Invoke(New Action(Of String)(AddressOf guiAdd), data)
Else
Dim fitem As New ListViewItem
fitem.Text = data
'Form1.lvsearch.Items.Add(fitem) <---Original Version
Form1.lvsearch.Items.Add(New ListViewItem("WTF!!!!")) '<--- Sanity Version
End If
End Sub
以下是完整的课程:
Imports System.Threading
Imports System.Threading.Thread
Imports System.IO
Imports System.Net
Public Class craigsearcher
Private cURL As String 'Class scope variables preceded by "c"
Private cSER As Integer
Public Sub New(ByVal fURL As String, Optional ByVal autoStart As Boolean = True)
Try
cURL = fURL 'Function scope variables preceded by "f"
serialGen()
If autoStart = True Then
invokeSearch()
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub invokeSearch()
Dim cTHREAD As New Threading.Thread(AddressOf search)
cTHREAD.IsBackground = True
cTHREAD.Start()
End Sub
Private Sub serialGen()
'Random number to track this threads temp files
Dim fRND As Double
Dim fINT As Integer
Randomize()
fRND = Rnd() * 1000000000
fINT = Math.Floor(fRND)
cSER = fINT.ToString
End Sub
Private Sub search()
'Class Workflow
prepData()
extractData()
'MessageBox.Show("Debug: End of Thread")
End Sub
Private Sub prepData()
'WIP: This is just proof of concept currently.
'Needs revision, but get the job done for now.
Dim client As New WebClient()
Dim rawHTML As String = client.DownloadString(New Uri(cURL))
Dim fo As New StreamWriter(".\temp\" & cSER & ".dat")
fo.WriteLine(rawHTML)
fo.Close()
Thread.Sleep(25)
Dim fo2 As New StreamReader(".\temp\" & cSER & ".dat")
Dim fo2str As String = ""
Do Until fo2.EndOfStream = True
fo2str = fo2str & Trim(fo2.ReadLine()) & vbCrLf
Loop
fo2.Close()
Thread.Sleep(25)
System.IO.File.Delete(".\temp\" & cSER & ".dat")
Dim fo3 As New StreamWriter(".\temp\Prep" & cSER & ".dat")
fo3.WriteLine(fo2str)
fo3.Close()
Thread.Sleep(25)
End Sub
Private Sub extractData()
'WIP: This is just proof of concept currently.
Dim fo As New StreamReader(".\temp\Prep" & cSER & ".dat")
Dim fstr As String = ""
Do Until fo.EndOfStream = True
fstr = fo.ReadLine()
If InStr(fstr, "<p class=") Then
'FUTURE LOGIC AND STUFFS SORTED HERE. Regex etc.
guiAdd(fstr)
End If
Loop
End Sub
Public Sub guiAdd(ByVal data As String)
If Form1.lvsearch.InvokeRequired Then
Form1.lvsearch.Invoke(New Action(Of String)(AddressOf guiAdd), data)
Else
Dim fitem As New ListViewItem
fitem.Text = data
'Form1.lvsearch.Items.Add(fitem) <---Original Version
Form1.lvsearch.Items.Add(New ListViewItem("WTF!!!!")) '<--- Sanity Version
End If
End Sub
End Class
这是类实例化的方式:
Dim worker As New craigsearcher("http://atlanta.craigslist.org/ggg/", True)
所以,这就是我拥有的一切。我意识到解析代码需要修改/完成。我会接受它。这是概念证明阶段。传递正确的数据类型。我只需要帮助理解为什么addGUI()无法正常运行。我对多线程世界并不是特别精通,所以我很高兴我能做到这一点。
我一直以此为指导: http://www.vbforums.com/showthread.php?682082-Understanding-Multi-Threading-in-VB-Net
答案 0 :(得分:0)
尝试修改此方法:
Private Sub search()
'Class Workflow
prepData()
extractData()
'MessageBox.Show("Debug: End of Thread")
End Sub
到这个
Private Sub search()
'Class Workflow
Thread.QueueUserWorkItem(prepData)
Thread.QueueUserWorkItem(extractData)
'MessageBox.Show("Debug: End of Thread")
End Sub
尝试将其放在线程池上。这意味着让第一个方法在第二个方法之前完成。如果你把它放在线程上,它应该按时间顺序排列。这可能是因为extractData()方法首先完成了它的处理而不是prepData()方法。
希望它有所帮助。
答案 1 :(得分:0)
您是否在没有单独的工作人员/线程的情况下对此进行了测试?
这应该是你的形式,而不是你的工人类/线程:
如果您愿意,可以将它放在listview控件中,只需确保您可以从其他类中引用它。
Private Delegate Sub invokeGuiAdd(ByVal data As String)
Public Sub guiAdd(ByVal data As String)
If InvokeRequired Then
'Form1.lvsearch.Invoke(New Action(Of String)(AddressOf guiAdd), data)
Invoke(New invokeGuiAdd(AddressOf guiAdd), New Object() {data})
Else
Dim fitem As New ListViewItem
fitem.Text = data
'Form1.lvsearch.Items.Add(fitem) <---Original Version
lvsearch.Items.Add(New ListViewItem("WTF!!!!")) '<--- Sanity Version
End If
End Sub
和
Form1.guiAdd(fstr)
哦,作为旁注,事件是代理人,因此您可以使用事件。