从BackgroundWorker填充DataGridView

时间:2014-07-25 11:00:04

标签: vb.net winforms visual-studio-2012 datagridview backgroundworker

情况如此:
我的表单中有DataGridView,当我开始填写表单DGV时,应该开始填写BackgroundWorker

Private Sub FirstSub()
    adoconn()
    Me.Enabled = False
    bw.RunWorkerAsync()
    Me.Enabled = True
End Sub

Private Sub bw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bw.DoWork

    Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
    If DataGridView1.InvokeRequired Then
        '//For VB 10 you can use an anonymous sub
        DataGridView1.Invoke(Sub() bw_DoWork(sender, e))
    Else


        Try
            DataBaseLayer.FillDTwithSP("ArticlesSelect", ds_Tables.Articles)
            Me.DataGridView1.DataSource = ds_Tables.Articles
            Me.DataGridView1.ClearSelection()

        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try
    End If

End Sub

在Carlos给我一个我应该做什么的例子后,我做了这个,但现在我有一个问题,当我放置BrakePoint时甚至没有进入bw_DoWork sub

Private Sub FirstSub()
    adoconn()
    Me.Enabled = False
    bw.WorkerReportsProgress = True
    AddHandler bw.DoWork, AddressOf bw_DoWork
    AddHandler bw.ProgressChanged, AddressOf bw_ProgressChanged
    Me.Enabled = True
End Sub
Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
    Try
        DataBaseLayer.FillDTwithSP("ArticlesSelect", ds_Tables.Articles)
            Me.DataGridView1.DataSource = ds_Tables.Articles
            Me.DataGridView1.ClearSelection()
    Catch ex As Exception
        MsgBox(ex.ToString)
    End Try
End Sub
Private Sub bw_DoWork(sender As Object, e As DoWorkEventArgs)
    Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
    bw.ReportProgress(sender, e)
End Sub

所以,我想要的是禁用表单上的所有控件,直到我的DataTable被填充并且DataGridView显示DT的结果集。 问题是,当我加载此表单时,它会在完成所有操作后再次冻结和取消冻结,因此根本不会产生BackgroundWorker的影响。

如果您需要更多信息或代码部分,请随时告诉我,以便我可以解决此问题。

谢谢,
呼和

2 个答案:

答案 0 :(得分:2)

在回顾了这个主题的一些细节之后,我可以指出一些我看到的内容。

  1. 您正试图在ProgressChanged Event中设置来源,如果您有代表并且正确使用它,则无需使用。
  2. Progress Changed Event只应用于报告进度,而不是更改用户界面或任何控件。
  3. 无需添加处理程序,因为它们已被处理。
  4. 我不确定您的调用FirstSub方法在哪里,我会假设从加载事件或点击事件中,这无论如何都不重要。以下是我所做的更改,应该对您有益。您还可以查看我的其他答案herehere,两者都非常适合您参考并了解需要进行的操作。

     Delegate Sub SetDataTable(ByVal dt As DataTable) 'Your delegate..
    
     Private Sub FirstSub()
        adoconn()
        Me.Enabled = False
        bw.RunWorkerAsync()
        Me.Enabled = True
     End Sub
    
     'The method that fills DataGridView1
     Private Sub AddSource(ByVal dt As DataTable)
        If Me.DataGridView1.InvokeRequired Then 'Invoke if required...
            Dim d As New SetDataTable(AddressOf AddSource) 
            Me.Invoke(d, New Object() {dt})
        Else 'Otherwise, no invoke required...
            Me.DataGridView1.DataSource = dt
            Me.DataGridView1.ClearSelection()
        End If
     End Sub
    
     Private Sub bw_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
        If Not (bw.CancellationPending) Then
            DataBaseLayer.FillDTwithSP("ArticlesSelect", ds_Tables.Articles)
            AddSource(ds_Tables.Articles)
        ElseIf (bw.CancellationPending) Then
            e.Cancel = True
        End If
     End Sub
    

    请告诉我这是如何为您解决的,并查看我给您的其他两个链接。另请注意,您可以将DoWork中的调用更改为方法AddSource,以便不通过DataTable并调用它...

    MrCodexer

答案 1 :(得分:0)

您应该使用Event ProgressChanged来执行UI线程中的代码,以便您可以安全地更新控件:

_backgroundWorker.ProgressChanged += New ProgressChangedEventHandler(backgroundWorker_ProgressChanged)

在Do_Work内部,调用这样的进度:

 //param is the value you need to update your controls
  _backgroundWorker.ReportProgress(p, param)

  Private Sub backgroundWorker_ProgressChanged(sender As Object, e As    ProgressChangedEventArgs)

       ' Update the UI here         
  End Sub

无需使用InvokeRequired insode ProgressChanged事件。