我有一个带有2个按钮的表单,用于填充2个不同的数据网页。
有一个泛型函数,它接受一个SQL语句并执行它。
根据SQL语句的不同,这可能需要一些时间来执行 - 因此我不想锁定UI,而是使用BackgroundWorker,以便在查询运行时显示加载屏幕。
这是没有BGW的初始代码:
Public Class Form1
Private Sub Query1Button_Click(sender As System.Object, e As System.EventArgs) Handles Query1Button.Click
Dim sql As String = "SELECT col_1 FROM TABLE_1"
Dim query1DT As DataTable = getData(sql)
'now do some other stuff with the datatable
DataGridView1.DataSource = query2DT
End Sub
Private Sub Query2Button_Click(sender As System.Object, e As System.EventArgs) Handles Query2Button.Click
Dim sql As String = "WHILE 1=1 SELECT col_2 FROM TABLE_2" 'long running query
Dim query2DT As DataTable = getData(sql)
'now do some other stuff with the datatable
DataGridView2.DataSource = query2DT
End Sub
Public Shared Function getData(ByVal sql As String) As DataTable
Dim sqlcon As New SqlClient.SqlConnection
Dim sqlcomm As New SqlClient.SqlCommand
Dim sqlda As New SqlClient.SqlDataAdapter
Dim sqldt As New DataTable
sqlcon.ConnectionString = "DBConnection"
sqlcon.Open()
sqlcomm.Connection = sqlcon
sqlcomm.CommandText = sql
sqlda.SelectCommand = sqlcomm
sqlda.Fill(sqldt)
Return sqldt
End Function
End Class
我想将getData函数包装在一个新的BGW线程中,但我不确定如何做到这一点,因为我想填充两个不同的datatables / datagrids。
如果只有1个datagrid,我会怎么做: Imports System.ComponentModel
Public Class Form3
Private Sub Query1Button_Click(sender As System.Object, e As System.EventArgs) Handles Query1Button.Click
Dim sql As String = "SELECT col_1 FROM TABLE_1"
getDataInBackground(sql)
End Sub
Private Sub Query2Button_Click(sender As System.Object, e As System.EventArgs) Handles Query2Button.Click
Dim sql As String = "WHILE 1=1 SELECT col_2 FROM TABLE_2" 'long running query
Dim query2DT As DataTable = getData(sql)
'now do some other stuff with the datatable
DataGridView2.DataSource = query2DT
End Sub
Public Sub getDataInBackground(ByVal sql As String)
'setup worker
Dim bw As BackgroundWorker = New BackgroundWorker()
bw.WorkerReportsProgress = True
bw.WorkerSupportsCancellation = True
AddHandler bw.DoWork, New DoWorkEventHandler(AddressOf bw_DoWork)
AddHandler bw.RunWorkerCompleted, New RunWorkerCompletedEventHandler(AddressOf bw_RunWorkerCompleted)
AddHandler bw.ProgressChanged, New ProgressChangedEventHandler(AddressOf bw_ProgressChanged)
'Run worker
bw.RunWorkerAsync(sql)
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
Dim returnDT As DataTable
returnDT = getData(e.Argument)
e.Result = returnDT
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
If e.Cancelled = True Then
StatusLabel.Text = "Cancelled!"
ElseIf e.Error IsNot Nothing Then
StatusLabel.Text = "Error: " & e.Error.Message
Else
'now do some other stuff with the datatable
DataGridView1.DataSource = e.Result
StatusLabel.Text = "Done!"
End If
End Sub
Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
'show loading status
StatusLabel.Text = "Running"
End Sub
Public Shared Function getData(ByVal sql As String) As DataTable
Dim sqlcon As New SqlClient.SqlConnection
Dim sqlcomm As New SqlClient.SqlCommand
Dim sqlda As New SqlClient.SqlDataAdapter
Dim sqldt As New DataTable
sqlcon.ConnectionString = "DBConnection"
sqlcon.Open()
sqlcomm.Connection = sqlcon
sqlcomm.CommandText = sql
sqlda.SelectCommand = sqlcomm
sqlda.Fill(sqldt)
Return sqldt
End Function
End Class
如何使BGW更具通用性,以便我不必在bw_RunWorkerCompleted子内部“现在对数据表执行其他操作”?
答案 0 :(得分:0)
我认为您可以使用await
模式。而不是将你的逻辑放入工作者,因为如果它在完成的事件中,它更像是函数式编程。
await
关键字将封装您的后台请求。我不会详细介绍,但有很多教程。它基本上允许您调用操作而不会堵塞UI线程,一旦完成,您的代码将继续在下一行。
http://www.youtube.com/watch?v=ZyFL3hjHADs是我用来学习它的教程。