教程中国
PHOTOSHOP CS9.0中文版 MAYA 8.5 FOR WINDOWS Corel Painter v9.0 Flash MX2004 中文版 Illustrator cs2 中文版
VC++6.0含sp6 中英文版 VB6.0 +sp6 简体中文版 Borland Delphi 7汉化版 MSDN for vb6.0中文版 Visual Studio 2005简体
教程中国下属 文件存储共享专家BIBIDU.COM 提供大型软件,教材,源码,电影,音乐,图书等下载 更多精品请点此进入
  您目前所在位置: 教程中国 >> .NET类 >> VB.NET >> 用Visual Basic.Net创建多线程应用程序 RSS订阅
用Visual Basic.Net创建多线程应用程序
用Visual Basic.Net创建多线程应用程序(2)
教程(视频,书籍)下载:  ASP.NET AutoCAD 数据库 C# ASP java photoshop 网页设计 delphi 3dmax Flash C++ VB 张孝祥 实例   更多请进入BIBIDU搜索
IT搜索引擎   
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

Return
End Sub

  很明显,critical sections仅应该在需要的时候创建,因为它们会阻塞线程,从而会影响整体的吞吐量。

 要同步线程间共享的实例变量,有一个很简单的技巧,这就是使用Interlocket类。该类包含有共享的Increment和Decrement方法,可以将修改变量和检查结果的操作结合成一个单一的操作。这样做是必需的,因为一个线程可以修改变量的值,在接着检查结果之前,它的运行时间就结束了。在该线程再次运行时,变量的值就有可能被其它的线程修改了。

  例如下面的代码增加Instructors类的mPhotosProcessed实例级变量的值:

Interlocked.Increment(mPhotosProcessed)

  Interlocked类还支持Exchange和CompareExchange的方法,它们的作用分别是设置变量为特定的值,或者在该变量等于某个值时才这样做。

  使用线程本地存储

  虽然在理想的情况下你的线程将使用私有的实例变量,不过在许多时候,当你的线程运行一个对象的方法,而该方法可能被其它的线程共享时,这样你的线程可能需要存储和接收它自己的真正私有数据。例如,当一个线程池中的线程监视一个MSMQ队列,并且需要取得队列中数据,然后存储下来作以后处理用时,就会出现这种情形。

  在Windows/Article/czxt/Index.html">操作系统中,每个线程都拥有自己的线程本地存储(thread local storage,TLS),以用来跟踪状态信息。方便的是,Thread类拥有一套方法,可方便地创建和维护TLS中的内存区域(该区域称为data slots)。

  值得一提的是,Thread类拥有一个共享的AllocateNamedDataSlot方法,可以使用指定的名字为AppDomain中的所有线程创建一个新的data slot。该slot可以在随后通过使用SetData和GetData方法设置和读取。例如,假定有一个称为WorkerClass类执行一些处理活动,并且我们想创建一定数量的线程来执行该工作。以下的代码段为所有的线程创建了一个称为“ID”的data slot,然后通过objWorker实例的StartWork方法,执行相应数量的线程:

Dim dssSlot As LocalDataStoreSlot
Dim tNew As Thread
Dim objWorker As WorkerClass

dssSlot = Thread.AllocateNamedDataSlot("ID")

For i = 0 to intMaxThreads
 tNew = New Thread(New ThreadStart(AddressOf objWorker.StartWork)
 tNew.Start
Next


  要注意的是由于所有的新线程将会共享objWorker上的实例变量,因此StartWorker方法和任何通过Start调用的方法将需要使用同步以防止对这些变量的同时访问。不过,如果每个线程需要它们自己的数据在方法间共享,它们可以将一个拷贝放到TLS的“ID”slot中,如下所示。

Public Sub Start()
 Dim dssIDSlot As LocalDataStoreSlot
 Dim myID As Integer

 ' Do other work

 dssIDSlot = Thread.GetNamedDataSlot("ID")
 Thread.SetData(dssIDSlot, myID)
 Call NextProcess()
End Sub

Private Sub NextProcess()
 Dim myID As Integer
 Dim dssIDSlot As LocalDataStoreSlot

 dssIDSlot = Thread.GetNamedDataSlot("ID")
 myID = Thread.GetData(dssIDSlot)

 ' Do other work
End Sub

  当NextProcess方法被调用时,数据可以再次通过使用Getdata由slot中读取。

  再次提醒一下,上面提到的设计模式在需要时才使用。只有在你的设计是很复杂而且需要从多个线程中访问同样的对象时,你才需要使用TLS。

 使用线程工具

  你可以通过Thread类来创建和管理自己的线程,System.Threading命名空间还提供了一个简单的方式来使用线程,这些线程由CLR分配的一个池得到。这样做是可能的,因为CLR自动在每个进程创建和管理一个线程池,这样做是为了用来处理异步的操作,例如I/O和&&事件。在池中,一个线程被分配Highest优先权利,它是用来监视队列中其它线程的状态的。使用ThreadPool类,你的代码可接进这个池,并且可以更有效地使用这个在运行时已经配置的体系。实际上,ThreadPool类可允许你提交工作项目(例如要执行的方法)到池中,它们会被随后的工作线程执行。

  如前所述,只有在应用需要的时候才使用线程,并且要经过仔细的分析。例如,使用线程池的一个很好的情形是,一个用来监听由一个或者多个信息队列中进入的新信息的Windows服务应用。虽然System.Messaging命名空间支持异步的操作,但是创建一个线程池可允许你控制一些特别的方面,例如有多少线程在处理信息和线程的生存时间。

  下面例子是一个经过简化的类,它使用ThreadPool类,用来监听一个MSMQ队列。

  列表11.9 QueueListener类,该类使用ThreadPool类来监听一个MSMQ队列

Option Strict Off

Imports System
Imports System.Threading
Imports System.Messaging
Imports Microsoft.VisualBasic

Public Class QueueListener
' Used to listen for MSMQ messages

 Protected Class EventState
 ' Used to store the event and any other state data required by the listener
  Public ResetEvent As ManualResetEvent
  Public ThreadName As String

  Public Overloads Sub New(ByVal myEvent As ManualResetEvent)
   MyBase.New()
   ResetEvent = myEvent
  End Sub
  
  Public Overloads Sub New(ByVal myEvent As ManualResetEvent, ByVal Name As String)
   MyBase.New()
   ResetEvent = myEvent
   ThreadName = Name
  End Sub
End Class


Private mstrMachine As String
Private mstrQueue As String
Private mWorkItems As Integer = 7
Private mFinished As Boolean = False
Dim mEvs() As ManualResetEvent

Public Property WorkItems() As Integer
Get
 Return mWorkItems
End Get
Set(ByVal Value As Integer)
 If Value > 15 Then
  mWorkItems = 15
 Else
  mWorkItems = Value
 End If
End Set
End Property

Public Sub New(ByVal Machine As String, ByVal Queue As String)
' Constructor accepts the necessary queue information
 mstrMachine = Machine
 mstrQueue = Queue
End Sub

Public Sub Listen(ByVal state As Object)
 ' Method that each thread uses to listen for messages

 ' Create a MessageQueue object
 Dim objMQ As System.Messaging.MessageQueue = New System.Messaging.MessageQueue()
 ' Create a Message object
 Dim objMsg As System.Messaging.Message ' = New System.Messaging.Message()
 ' Event from the state

来源:十度教育
作者:
关键字:用Visual
发表日期:2006-5-26 0:40:35

网页显示有限 阅读全文请下载本文完整版WORD文档

上一篇:在VB.NET中使用抽象类   下一篇:体验Visual Basic.Net的继承和重载


共4页 9 7 [1] [2] [3] [48 :>

2008-12-4 4:36:12
本文的相类似文章
  • 巧用Visual Basic的Timer控件
  • 用Visual Basic自编小游戏
  • 用Visual Basic设计窗体背景花纹
  • 用Visual Basic设计Windows门禁程序
  • 用Visual Basic自编小游戏
  • 用Visual Basic .Net发送电子邮件
  • 用Visual Basic.Net创建多线程应用程序
  • 利用Visual Basic设计多媒体应用程序
  • 利用Visual Basic开发微软代理控件
  • 用Visual Basic开发数据库浏览器
  • 在学习中进步 在进步中成长 教程中国相随您的成长之路
    华腾联合科技股份有限公司版权所有
    广告联系:Rosibo@163.com