1

バックグラウンド ワーカーとマルチスレッドに関する SO に関する多くの記事を読んだ後、私はあなたの意見を聞きたい作業コードを持っています。課題は、別のスレッドでデータを取得し、コンテンツで UI を更新することです。Invoke で問題が発生したため、ランタイム BGW を使用しました。RunWorkerCompleted の利便性と同様に。

コードを見て、そのアプローチが合理的で適切かどうかを確認していただけますか? (進行状況の更新などは追加していません。)

Public Class BgwArgs                'args object to pass to BGW
    Public sSql As String           'query to be run by DoWork
    Public dbTable As DataTable     'return data to this table
    Public lst As ListBox           'populate this control with returned data
End Class

Private Sub btnStart_Click(sender As System.Object, e As System.EventArgs) Handles btnStart.Click
    'get new BGW, may be multiple BGW's running at a time
    Dim myBgw As BackgroundWorker = fGetBgw()
    Dim sArgs As New BgwArgs   'set Args
    sArgs.sSql = "BHRow"       'just a test string, would really be a query
    sArgs.lst = lstBH          'control to populate
    myBgw.RunWorkerAsync(sArgs)
End Sub

Private Function fGetBgw() As BackgroundWorker
   'create New backgroundworker and addhandlers
    Dim newBgw As New BackgroundWorker
    myBgw.WorkerReportsProgress = True
    myBgw.WorkerSupportsCancellation = True
    AddHandler myBgw.DoWork, AddressOf WorkerDoWork
    AddHandler myBgw.ProgressChanged, AddressOf WorkerProgressChanged
    AddHandler myBgw.RunWorkerCompleted, AddressOf WorkerCompleted
    Return newBgw
End Function

Private Sub WorkerDoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
    Thread.Sleep(3000)  'kill time as a test
    Dim sArgs As BgwArgs = e.Argument
    pGetDbTable(sArgs)    'pass in Args to DataQuery
    e.Result = sArgs      'set result for use in Completed event
End Sub

Private Sub WorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs)
    Dim sArgs As BgwArgs = e.Result
    Dim tbl As DataTable = sArgs.dbTable
    Dim lb As ListBox = sArgs.lst
    Dim thisBgw As BackgroundWorker = CType(sender, BackgroundWorker)

    If e.Cancelled = True Then

    ElseIf e.Error IsNot Nothing Then
        MsgBox(e.Error.Message)

    Else

        For Each row As DataRow In tbl.Rows
            'update UI, bind data here, etc.
            lb.Items.Add(row("col1").ToString)
        Next
        RemoveHandler thisBgw.DoWork, AddressOf WorkerDoWork
        RemoveHandler thisBgw.ProgressChanged, AddressOf WorkerProgressChanged
        RemoveHandler thisBgw.RunWorkerCompleted, AddressOf WorkerCompleted
     Endif

End Sub

Private Sub pGetDbTable(sArgs As BgwArgs)
    Dim tbl As New DataTable
    'would really run a SQL query here... and return the Datatable
    With tbl
        .Columns.Add("col1")
        Dim i As Integer
        For i = 0 To 200
            .Rows.Add(sArgs.sSql & i)
        Next
        sArgs.dbTable = tbl
    End With
End Sub
4

0 に答える 0