手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>网络编程>Asp.Net编程>列表

用Visual Basic.Net创建多线程应用程序

来源:互联网 作者:西部数码 时间:2008-04-09
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!


  注意:ThreadPriority枚举对象和Win32 API的32个级别是有对应关系的,实际上,最低的优先权(Lowest)对应6,而最高的(Highest)为10。

  然后代码就设置了线程的Name属性,开始看来有点奇怪,因为一个线程或者是它的名字应该永远都不会在用户的界面上出现,这个名字其实是出现在调试器中,也可用作日志的用途。接着就是执行Start方法来真正开始执行。

  技巧

  有时得到线程的一个数字标识来作日志和汇报目的是非常方便的。你可以调用CurrentThread属性或者Thread类上的GetHashCode方法。这将会返回一个数字,你可以用它来在应用中作记录或者事件日志。

  启动线程后,代码就进入一个循环等待,检查ThreadState属性的值是否为Unstarted(这是线程的初始状态),直到线程启动。ThreadState枚举还包括有9个其它的状态,由Running到Stopped。要注意的是调用Thread类的共享方法Sleep将会令该线程休眠指定的毫秒数,在这里是主线程而不是tPhoto表示的线程。最后,在执行一些其它的工作后,主线程通过检查IsAlive属性来看tPhoto是否仍然运行。如果是的话,就会在调用Join方法前,向用户展示相应的信息。该方法通过阻塞来同步两个线程(挂起当前执行的线程)。直到调用该方法的线程停下来为止。

  技巧

  与上面提到的Priority属性无关,CLR会区分前台运行的线程和后台运行的线程。如果一个线程被标识为后台线程,CLR在AppDomain关闭的时候并不会等待它完成。如前面讨论的那样,在使用异步文件IO时,运行时创建的线程都是后台的线程,因此你要确保代码的主线程不会在I/O完成前退出。默认的情况下,上面创建的线程被标识为前台,同时它们的IsBackgropu属性被设置为False。

  虽然在代码中并没有展示,不过在线程执行的时候它可以通过Suspend方法挂起,然后通过Resume继续执行。此外线程还可以通过使用Abort方法退出,这时将会在线程内抛出一个例外。
156
  对资源的同步访问

  一般来说,你希望在独立的线程中运行各种处理,而不需要访问共享的资源。建议的方法如下:

  1、封装要运行的处理到一个类中,并且留一个入口来启动该处理,例如Public Sub Start()并且初始化变量来处理状态

  2、创建一个独立的类实例

  3、设置处理需要的实例变量

  4、在一个独立的线程中调用入口

  5、不要引用该类的实例变量

  只要使用这个方法,全部的实例变量对于线程都是“私有的”,因此可以无需担心同步的问题。

  不过,有时这种情况是不能避免的,例如数据库连接或者文件处理。为了确保某线程在访问这些资源时其它线程处于等待状态,你可以使用Monitor类和它的相关方法,包括有Enter, Exit, TryEnter, Wait, Pulse和PulseAll。

  例如,假定上面代码中的Instructors类包含了一个类级的SqlConnection对象,该对象被所有的方法共享,并且用来连接数据库。这就是一个资源共享的例子,它被类中的所有方法所共享。

  注意:

  虽然使用连接池可提供一个更富扩展性的方案,不过这个例子满足我们当前的需要,它让所有的数据库访问通过一个单一的数据库连接进行。这种方式对于需要一个持久的数据库连接的应用是适合的,不过不适合用在分布式的应用。

  这个例子中,我们假设在调用GetPhotos后,客户端继续调用一个使用该连接对象的方法。由于连接可能正在被GetPhotos使用,如果SqlConnection正在忙于处理其它的结果,该方法将会抛出一个例外。

  要避免这种情形,GetPhotos方法可以使用Monitor的共享方法在其代码中创建critical section。简单说来,critical section就是调用Monitor类的Enter和Exit方法所构成的代码块,通过它,访问的同步是基于传送至Enter方法的对象。也就是说,如果GetPhotos方法要独立地使用SqlConnection,它必须要创建一个critical section,在该section的开始部分,通过传送SqlConnection到Monitor的Enter方法中,并且在结束的时候调用Exit方法。被传送的对象可以是任何继承System.Object的对象。

  如果该对象正在被其它的线程使用,Enter方法将会阻塞直到对象被释放。你也可以调用TryEnter方法,该方法不会阻塞,它只会返回一个布尔值指示该对象是否在使用中。一旦进入critical section,GetPhotos方法可以使用SqlConnection执行一个存储过程,并且将结果写出来。在关闭结果集SqlDataReader后,就会调用Monitor类的Pulse方法,以通知等待队列中的下个线程该对象已经释放了。然后就会将线程移动到ready队列中,以便准备开始处理。PulseAll方法则通知全部的等待线程该对象准备被释放。最后就会调用Exit,从而释放monitor并且结束critical section部分。这部分代码的框架见下。

  同步的资源。以下的例子展示了GetPhotos方法将使用Monitor类来确保两个线程不会同时使用SqlConnection对象

Public Sub GetPhotos()

Dim cmSQL As SqlCommand
Dim sdrIns As SqlDataReader

Try
' Execute proc
cmSQL = New SqlCommand("usp_GetPhotos", mcnSQL)
cmSQL.CommandType = CommandType.StoredProcedure

' Enter critical section
Monitor.Enter(mcnSQL)
' Alternate code
' Do While Not Monitor.TryEnter(mcnSQL)
' Thread.CurrentThread.Sleep(100)
' Loop
sdrIns = cmSQL.ExecuteReader()
Catch e As Exception
End Try

Do While sdrIns.Read
' Read the data and write it to a binary stream
Loop

sdrIns.Close
Monitor.Pulse(mcnSQL)
Monitor.Exit(mcnSQL)
' Exited critical section

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!