vb.net 从 BackgroundWorker 填充 DataGridView

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24954223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 17:54:10  来源:igfitidea点击:

Filling DataGridView from BackgroundWorker

vb.netwinformsvisual-studio-2012datagridviewbackgroundworker

提问by Hoh

This is the case:
I have a DataGridViewin form and when I start the form DGVshould start filling with BackgroundWorker.

情况是这样:
我有一个DataGridViewin 表单,当我开始时,表单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

After Carlos giving me an example of what should I do, I did this, but now I have a problem that when I place BrakePoint is doesn't even get into bw_DoWorksub

在 Carlos 给我举了一个我该怎么做的例子之后,我做了这个,但现在我遇到了一个问题,当我放置 BrakePoint 时,它甚至没有进入bw_DoWorksub

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

So, my desired thing is to disable all controls on form until my DataTableis filled and DataGridViewis showing a result set from DT. The thing is that when I load this form it freeze and un-freeze again when everything is done, so there is no effect of BackgroundWorkerat all.

所以,我想要的是禁用表单上的所有控件,直到我DataTable填写并DataGridView显示来自DT. 问题是,当我加载此表单时,它会在一切完成后再次冻结和解冻,因此根本没有影响BackgroundWorker

If you need any more info or code parts feel free to tell me so I can solve this problem.

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

Thanks,
Hoh

谢谢,
呵呵

回答by ???ěxě?

After reviewing some of the details of this thread I can point out a few things I see.

在查看了这个线程的一些细节之后,我可以指出一些我看到的东西。

  1. You are trying to set your source in ProgressChanged Event, no need if you have a delegate and use it properly.
  2. The Progress Changed Eventshould only be used to report progress, not change UI or any controls.
  3. No need to add handlers as they are already taken care of.
  1. 您正在尝试将源设置为ProgressChanged Event,如果您有委托并正确使用它,则不需要。
  2. Progress Changed Event应只用于报告进度,不改变用户界面或任何控制。
  3. 无需添加处理程序,因为它们已经得到处理。

I am not sure where your calling FirstSubmethod, I would assume from a load event or click event perhaps, that doesn't matter anyways. Below are changes that I made and should be good for you. You can also check out my other answer's hereand here, both are great for you to reference and see what need's to take place.

我不确定您的调用FirstSub方法在哪里,我可能会从加载事件或点击事件中假设,无论如何这都无关紧要。以下是我所做的更改,应该对您有好处。您也可以在此处此处查看我的其他答案,两者都非常适合您参考并了解需要进行哪些操作。

 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

Let me know how this works out for you and check the other two links I gave you. Also on another note you could change the call in the DoWorkto your method AddSource to not pass the DataTableand just call it...

让我知道这对你有什么影响,并检查我给你的另外两个链接。另外,在另一个注意事项中,您可以更改DoWork对您的方法 AddSource的调用,以不传递该DataTable调用而只调用它...

MrCodexer

程序员先生

回答by Carlos Landeras

You should use the Event ProgressChanged, that executes the code in the UI thread, so you can safely update your controls:

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

_backgroundWorker.ProgressChanged += New ProgressChangedEventHandler(backgroundWorker_ProgressChanged)

Inside the Do_Work, invoke the progress like that:

在 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

No need to use InvokeRequired insode the ProgressChanged event.

无需在 ProgressChanged 事件中使用 InvokeRequired。