0

我有一个带有 2 个按钮的表单,这些按钮填充了 2 个不同的 datagridviews。

有一个通用函数接收一条 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 线程中,但鉴于我要填充两个不同的数据表/数据网格,我不确定该怎么做。

如果只有 1 个数据网格,我会这样做: 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 子中“现在对数据表做一些其他的事情”?

4

1 回答 1

0

我认为您也许可以使用该await模式。而不是将你的逻辑放入工作程序中,因为如果它在完成的事件中,它更像是函数式编程。

await关键字将封装您的后台请求。我不会详细介绍,但是那里有很多教程。它基本上可以让您在不阻塞 UI 线程的情况下调用操作,一旦完成,您的代码将在下一行继续。

http://www.youtube.com/watch?v=ZyFL3hjHADs是我用来学习它的教程。

于 2013-06-13T16:39:26.553 回答