VB 2010 (56)命令的异步执行

    目录

1.启动异步调用

2.AsyncCallback方法:

3.BindGrid方法定义一个BindGridDelegate委托

4.窗体的Invoke方法调用

5. 读取SqlDataReader数据动态创建DataTable


       在ADO.NET中,还允许Command对象异步执行它们的命令。对于很多应用程序,特别是Windows窗体应用程序来说,使用这个功能可以获得很大的性能提升,尤其在执行需要长时间运行的SQL语句时非常有效。
      SqICommand对象提供了3个不同的异步调用方法:BeginExecuteReader、BeginExecuteNonQuery和BeginExecuteXmIReader。每一个方法都有其对应的“结束”方法,包括EndExecuteReader、EndExecuteNonQucry和EndExecuteXmIReader。

1.启动异步调用

 Private Sub testAsynchronous()
        Dim sqlStr As String = "usp_Long_Running_Procedure"

        Dim conn As SqlConnection = GetConnection()
        conn.ConnectionString &= "; Asynchronous Processing=true;" '异步调用

        Dim comm As New SqlCommand(sqlStr, conn)
        comm.CommandType = CommandType.StoredProcedure

        conn.Open()
        comm.BeginExecuteReader(AddressOf Me.AsyncCallback, comm, CommandBehavior.CloseConnection)

    End Sub

  • 调用GetPubsConnection辅助方法,获得了一个对pubs数据库的连接口

Private Function GetConnection() As SqlConnection
        Return New SqlConnection(My.Settings.pubsConnectionString)
    End Function

  •  把"; Asynchronous Processing=true;"语句附加到Connection对象的连接字符串后面。这么做是为了让ADO.NET能够对SQL Server进行异步调用。
  • 设置好连接字符串后,创建SqICommand对象并把它初始化为可以执行usp Long Running_Procedure存储过程。这个存储过程通过SQL Server中的WAITFOR DELAY语句产生20秒的延迟,然后调用usp_Get_All存储过程。usp_Get_All存储过程可以选择作者表中的所有作者。这里加入延迟的目的是为了说明在上面的存储过程运行时,Windows窗体应用程序可以执行其他任务。下面是usp_Long-Running_Procedure和usp_Get_All存储过程的SQL代码:

ALTER PROCEDURE usp_Long_Running_Procedure
AS
SET NOCOUNT ON
WAITFOR DELAY '00:00:5'
EXEC usp_Get_All

ALTER PROCEDURE usp_Get_All
AS
SELECT
au_id,au_lname,au_fname,phone,address,city,state,zip,contract
From
authors

  • 最后一行代码调用了BeginExecuteReader方法。在这个调用中,首先传送一个System.AsyncCallback委托类型的委托方法(Me.AsyncCallback),在异步方法运行结束时,.NET Framework会使用这个委托返回。另外还传入了已经初始化的SqICommand对象,用于执行存储过程。最后一个参数是DataReader的CommandBehavior值,这里为commandBehavior.CloseConnection,其含义是在DataReader关闭时,自动关闭数据库的连接。

2.AsyncCallback方法:

Private Sub AsyncCallback(ByVal ar As IAsyncResult)
        Dim comm As SqlCommand = CType(ar.AsyncState, SqlCommand)
        Dim reader As SqlDataReader = comm.EndExecuteReader(ar)
        Dim table As DataTable = GetTableFromReader(reader, "Authors")
        Me.Invoke(New BindGridDelegate(AddressOf Me.BindGrid), New Object() {table})
    End Sub

  • 第一行代码从传入的IAsyncResult对象的AsyncState属性中获得了SqICommand对象。前面调用BeginExecuteReader方法时,传入了自己的SqlCommand对象,以便在下一行调用EndExecuteReader方法。这个方法返回了SqIDataReader对象.
  • 第二行代码将SqIDataReader对象转换为DataTable类型(在后面讨论DataSct时将介绍转换的概念).
  •  最后一行非常重要。如果尝试在这里把DataTable对象绑定到网格,就会出现错误,因为当前执行的线程不是主Windows线程,而用于进行数据绑定的辅助方法BindGrid只能在Windows主线程环境内调用。为了把数据返回给主Windows线程,必须使用Form对象的Invoke方法将数据编组。 Invoke方法需要两个参数,希望调用的方法委托和方法用到的所有参数。

3.BindGrid方法定义一个BindGridDelegate委托

     Private Delegate Sub BindGridDelegate(ByVal table As DataTable)

    Private Sub BindGrid(ByVal table As DataTable)
        Me.DataGridView1.DataSource = Nothing
        Me.DataGridView1.DataSource = table
    End Sub

4.窗体的Invoke方法调用

Me.Invoke(New BindGridDelegate(AddressOf Me.BindGrid), New Object() {table})

    这行代码传入了一个新创建的BindGridDelegate委托实例,并用指向BindGrid方法的指针对其进行初始化。这样,正在执行查询的.NET工作线程就可以安全地与主Windows线程协同工作了。

5. 读取SqlDataReader数据动态创建DataTable

Private Function GetTableFromReader(ByVal reader As SqlDataReader, ByVal str As String) As DataTable
        Dim comm As SqlCommand = New SqlCommand("usp_Get_All", GetConnection)
        comm.CommandType = CommandType.StoredProcedure
        'Dim mReader As SqlDataReader
        comm.Connection.Open()

        reader = comm.ExecuteReader(CommandBehavior.CloseConnection)

        Dim dt As DataTable = New DataTable
        dt.TableName = str
        Dim schemaTable As DataTable = reader.GetSchemaTable()

        '动态构建表,添加列
        For Each dr As DataRow In schemaTable.Rows
            Dim dc As DataColumn = New DataColumn
            '设置列的数据类型()
            dc.DataType = dr(0).GetType()
            '设置列的名称()
            dc.ColumnName = dr(0).ToString()
            '将该列添加进构造的表中
            dt.Columns.Add(dc)
        Next
        '读取数据添加进表中
        While reader.Read()
            Dim row As DataRow = dt.NewRow()
            '填充一行数据
            For i = 0 To schemaTable.Rows.Count - 1
                row(i) = reader(i).ToString()
            Next
            dt.Rows.Add(row)
            row = Nothing
        End While
        reader.Close()
        schemaTable = Nothing
        Return dt
    End Function

Control.Invoke 方法

https://docs.microsoft.com/zh-cn/dotnet/api/system.windows.forms.control.invoke?view=netframework-4.8#System_Windows_Forms_Control_Invoke_System_Delegate_System_Object___

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ngbshzhn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值