使用VB.NET线程访问数据库

来源:互联网 发布:c语言母牛生小牛代码 编辑:程序博客网 时间:2024/05/16 10:49
线程是操作系统分配处理器时间的基本单元,线程可以在单个执行线程执行的同时运行多个活动,支持抢先多任务处理的操作系统可以创建多个线程并通过时间片轮转的方式使它们同时运行。在需要良好用户交互的应用以及与网络和数据库进行通讯的应用中,使用多线程能提供良好的交互体验,能对用户的要求做出快速的反应。本文主要介绍.NET中的线程在数据库编程中的具体应用(用VB.NET实现)。

  1 创建数据库访问线程

  在数据库应用中,特别是网络数据库访问,因为可能要访问的数据量较大,因此需要比较长的时间来得到结果,而一个良好的程序应具有良好的交互性,在访问数据库时应允许你的应用程序对用户的活动尽快做出响应,以提供丰富的用户体验。利用多线程机制可以让需要大量时间的操作在后台运行以快速响应用户的活动。下面的代码访问数据库并返回数据表:

Private sub GetDataFromDataBase()

m_table.Clear()
m_sqlDataAdapter.Fill(m_table)

End Sub
  创建Thread对象的新实例,需创建新的线程代理.ThreadStart线程代理可以指定生成线程时要执行的方法名,但线程代理并不实际运行线程.创建ThreadStart对象时,需指定线程开始执行时要运行的方法的指针,该方法不能接受任何参数。下面我们将上面的代码分配给一个线程处理,并且启动它:

Dim myThreadStart as ThreadStart =New ThreadStart(AddressOf GetDataFromDataBase)
Dim myThread as Thread=New Thread(myThreadStart)
myThread.Start()


  这样当进行数据库的访问时,用户可以继续进行处理。

2 将数据库访问方法封装到类

  上面提到,线程要执行的方法不能接受任何参数,如果要传入方法特定条件,可以将方法放在一个类中,在类中定义类的属性,需要时可以设置类的属性,然后用方法调用这些属性以实现方法参数类似的功能。同时,因为生成的线程在主应用程序线程之外运行,.net Framework提供线程隔离,这时如果要用新的线程操纵主应用程序中的对象便不被允许。最好的办法也是将线程要访问的对象包装在类中。下面我们创建一个类,封装属性和数据库访问方法:

Public Class dealDataBase
Private m_sqlDataAdapter As SqlDataAdapter
Private m_table As DataTable
Public Property setDataAdapter() As SqlDataAdapter
Get
setDataAdapter=m_sqlDataAdapter
End Get
Set(ByVal value As SqlDataAdapter)
m_sqlDataAdapter=value
End Set
End Property
Public Property setDataTable() As DataTable
Get
setDataTable=m_table
End Get
Set(ByVal value As DataTable)
m_DataTable=value
End Set
End Property
Public sub GetDataFromDataBase()

m_table.Clear()
m_sqlDataAdapter.Fill(m_table)

End Sub
End Class
  下面是创建线程并运行线程的代码:

Dim myDB As New dealDataBase ()
Dim myThreadStart as ThreadStart
Dim myThread as Thread
myDB.setDataAdapter=Me.DataAdapter1 'DataAdapter1是本窗体内定义的数据适配器
myDB.setDataTable=Me.DataTable1 'DataTable1是本窗体定义的数据表

myThreadStart=New ThreadStart(AddressOf myDB.GetDataFromDataBase)
myThread=New Thread(myThreadStart)
myThread.Start()

End Sub
  3 使用事件

  调用了线程的start方法,并不能确保其中的方法马上执行完,而要得到数据访问的结果又必须等其中的方法执行完毕。如果在运行线程后采用循环查询的方法显然影响了交互性,事件是从线程方法返回数据的好方法。只要在线程方法所在的类中定义一个事件,在线程方法中发出事件,而在窗体类中生成代理。
首先在dealDataBase类声明后加进事件:

Public Class dealDataBase
Public Event GetDataComplete(ByVal e As DtatTable)

End Class
  在类dealDataBase的GetDataFromDataBase()方法中加入发出事件的代码,放在m_sqlDataAdapter.Fill(m_table)后:

Public sub GetDataFromDataBase()

m_sqlDataAdapter.Fill(m_table)
RasiseEvent GetDataComplete(m_table)

End Sub

  下面在窗体类中生成代理

Private Sub dealData (ByVal e As DataTable)
'处理数据表
End Sub

  在创建线程并运行线程的代码中进行事件连接,事件连接代码放在运行线程前, dealDataBase类实例化后:

AddHandler myDB. GetDataComplete,AddressOf dealData

  这样,当线程方法执行完毕就会发出事件,而dealData方法会响应事件并做出处理。

4 同步机制

  当多个线程需要共享相同的对象时,因为每个线程都能改变对象的状态,因此会互相破坏对方的执行。为防止多个线程同时访问共享对象就需要同步。.net框架使用SyncLock…End SyncLock标识限制线程访问的代码段。 SyncLock可得到一个对象引用的唯一锁,只要将该对象传送给SyncLock.通过得到这个唯一锁,你可以确保多个线程不会访问共享的数据.比如要防止数据表DataTable1被多个进程同时访问,可以对要处理DataTable1的代码做如下处理:

 

SyncLock(DataTable1)
'处理DataTable1数据表的代码
End SyncLock

  5 总结

  线程的使用可以提高程序的效率和提供对用户活动的快速响应。但线程的使用比较复杂,并有死锁的可能,因此使用多线程一定要详细考虑资源的要求和潜在的冲突