0

初投稿はこちら。しかし、長い間潜んでいます。すぐに始めます。

ここでの私の小さなサイド プロジェクトは、craigslist から投稿を削除するアプリケーションです。スクレイピングされると、リスト データは「Form1」のリストボックスに送信されます。すべてのスクレイピングを処理するワーカー クラスを作成しました。クラス関数「guiAdd()」がリストボックスに適切に入力されない場合に問題が発生します。

Form1 が存在し、"lvsearch" という名前のリストボックス コントロールがあるとします。

これが問題だと私が認識している場所です: クラスサブルーチン

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

4

2 に答える 2

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

スレッドプールに置いてみてください。これは、最初のメソッドが 2 番目のメソッドよりも先に終了することを意味します。スレタイにすると時系列であるはずです。これはおそらく、prepData() メソッドではなく、extractData() メソッドが最初に処理を終了したためです。

それが役に立てば幸い。

于 2014-05-24T04:05:19.680 に答える
0

別のワーカー/スレッドなしでこれをテストしましたか?

これは、ワーカー クラス/スレッドではなく、フォーム内にある必要があります。

必要に応じて、リストビュー コントロールに配置できますが、他のクラスから参照できることを確認してください。

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)

補足として、イベントはデリゲートであるため、代わりにイベントを使用できます。

于 2014-05-24T04:13:18.957 に答える