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
Filling DataGridView from BackgroundWorker
提问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.
在查看了这个线程的一些细节之后,我可以指出一些我看到的东西。
- You are trying to set your source in
ProgressChanged Event, no need if you have a delegate and use it properly. - The
Progress Changed Eventshould only be used to report progress, not change UI or any controls. - No need to add handlers as they are already taken care of.
- 您正在尝试将源设置为
ProgressChanged Event,如果您有委托并正确使用它,则不需要。 - 本
Progress Changed Event应只用于报告进度,不改变用户界面或任何控制。 - 无需添加处理程序,因为它们已经得到处理。
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。

