当前位置: 首页 > news >正文

强化VB.NET编程多线程句柄技巧(转载)

  • 文章主要介绍了VB.NET编程,介绍了VB.NET编程中通常使用三类等待句柄:互斥对象、ManualResetEvent和AutoResetEvent。后两种通常用于同步事件。

 

VB.NET编程经过长时间的发展,很多用户都很了解VB.NET编程中多线程程序。多线程成为大多程序员苦恼的事,现在和大家交流一下多线程。多线程是可行的,因为操作系统是多任务的,它有模拟同一时刻运行多个应用程序的能力。尽管多数个人计算机只有一个处理器,但是现在的操作系统还是通过在多个执行代码片断之间划分处理器时间提供了多任务。线程可能是整个应用程序,但通常是应用程序可以单独运行的一个部分。操作系统根据线程的优先级和离最近运行的时间长短给每一个线程分配处理时间。多线程对于时间密集型事务(例如文件输入输出)应用程序的性能有很大的提高。VB.NET编程中通常使用三类等待句柄:互斥对象、ManualResetEvent和AutoResetEvent。后两种通常用于同步事件。

1.互斥对象

互斥对象都是同步对象,它们只能在一个时刻由一个线程拥有。实际上,互斥这个名字衍生自互斥对象的所有权是相互排斥的。当线程请求独占访问某种资源时,它们请求互斥对象的所有权。因为在某个时刻只有一个线程能拥有一个互斥对象,其它线程在使用资源前必须等待互斥对象的所有权。WaitOne方法引发一个调用线程等待互斥对象的所有权。如果拥有互斥对象的线程正常终止,该互斥对象的状态就被设置为signaled,下一个线程获得它的所有权。

2.同步事件

同步事件用于通知其它的线程发生了某种事情或者某种资源可用。不要被它使用了"事件"这个词迷惑了。同步事件与其它的VisualBasic事件不同,它是真正的等待句柄。与其它的等待句柄类似,同步事件有两种状态signaled 和nonsignaled。调用同步事件的某个等待方法的线程必须等待,直到其它线程调用Set方法给事件发信号。有两个同步事件类。线程使用Set方法把ManualResetEvent实例的状态设置为signaled。线程使用Reset方法或控制返回等待WaitOne调用把实例的状态设置为nonsignaled。AutoResetEvent类的实例也可以使用Set设置为signaled,但是只要通知等待线程事件变为signaled,它们自动返回到nonsignaled。

下面的例子使用AutoResetEvent类同步线程池事务。


 
  1. SubStartTest()  
  2. DimATAsNewAsyncTest()  
  3. AT.StartTask()  
  4. EndSub  
  5. ClassAsyncTest  
  6. PrivateSharedAsyncOpDoneAsNewSystem.Threading.AutoResetEvent(False)  
  7. SubStartTask()DimTpoolAsSystem.Threading.ThreadPoolDimargAsString="SomeArg" 
  8. Tpool.QueueUserWorkItem(NewSystem.Threading.WaitCallback(_AddressOfTask),arg)'对一个事务进行排队  
  9. AsyncOpDone.WaitOne()'等待该线程调用SetMsgBox("Threadisdone.")  
  10. EndSubSubTask(ByValArgAsObject)  
  11. MsgBox("Threadisstarting.")  
  12. System.Threading.Thread.Sleep(4000)'等待4秒.  
  13. MsgBox("Thestateobjectcontainsthestring"&CStr(Arg))  
  14. AsyncOpDone.Set()'发信号表明该线程完成了  
  15. EndSub  
  16. EndClass 

3.监视对象和同步锁

监视对象确保代码块的运行不被运行在其它线程中的代码打断。换句话说,其它线程中的代码不能运行,直到被同步的代码块结束。在VisualBasic .NET中使用SyncLock关键字来简化监视对象的访问。在VisualC# .NET中使用Lock关键字。

例如,假定你有一个程序,它重复地、异步读取数据并显示结果。使用优先多任务操作系统,正在运行的线程可以因为操作系统允许其它的线程运行而被打断。如果没有同步,数据正在显示时,显示数据的对象被其它的线程修改,有可能得到的是部分更新的数据视图。SyncLock保证一段代码持续运行,不被打断。下面的例子显示了怎样使用SyncLock给显示过程提供数据对象的独占访问。


 
  1. ClassDataObject  
  2. PublicObjTextAsString  
  3. PublicObjTimeStampAsDate  
  4. EndClassSubRunTasks()  
  5. DimMyDataObjectAsNewDataObject()  
  6. ReadDataAsync(MyDataObject)  
  7. SyncLockMyDataObject  
  8. DisplayResults(MyDataObject)  
  9. EndSyncLock  
  10. EndSub  
  11. SubReadDataAsync(ByRefMyDataObjectAsDataObject)'添加异步读取和处理数据的代码  
  12. EndSubSubDisplayResults(ByValMyDataObjectAsDataObject)'添加显示结果的代码  
  13. EndSub  

Interlocked类

你可以使用Interlocked类的方法防止多个线程同时更新或比较同一个值的问题发生。这个类的方法让你安全地增加、减少、交换和比较来自任何线程的值。下面的例子演示了怎样使用Increment方法增加一个运行在独立线程上的多个过程共享的变量的值。


 
  1. SubThreadA(ByRefIntAAsInteger)  
  2. System.Threading.Interlocked.Increment(IntA)  
  3. EndSub  
  4. SubThreadB(ByRefIntAAsInteger)  
  5. System.Threading.Interlocked.Increment(IntA)  
  6. EndSub 

ReaderWriter锁

在有些情况下,你可能希望只在写数据时锁定资源,在数据没有更新完前允许多个客户同时读数据。某个线程正在修改资源时,ReaderWriterLock类加强了对该资源的独占访问,但是允许读取资源的非独占访问。ReaderWriter锁是排他锁的一个有用的备选方案,排他锁引起其它线程等待,即使这些线程不需要更新数据。下面的例子演示了怎样使用ReaderWriter调整来自多个线程的读和写操作。


 
  1. ClassReadWrite  
  2. 'ReadData和WriteData方法可以被多个线程安全地调用  
  3. PublicReadWriteLockAsNewSystem.Threading.ReaderWriterLock()  
  4. SubReadData()'这个过程从数据源读取信息。在允许其它线程调用ReadData时,读取锁放置任何数据写入直到读取完成  
  5. ReadWriteLock.AcquireReaderLock(System.Threading.Timeout.Infinite)Try'此处执行数据操作  
  6. FinallyReadWriteLock.ReleaseReaderLock()'释放读取锁  
  7. EndTry  
  8. EndSubSubWriteData()'这个过程向数据源写信息。写入锁防止数据被读取或者写入知道线程完成写操作。  
  9. ReadWriteLock.AcquireWriterLock(System.Threading.Timeout.Infinite)Try'此处执行写操作  
  10. FinallyReadWriteLock.ReleaseWriterLock()'释放写入锁  
  11. EndTry  
  12. EndSub  
  13. EndClass 

结论

多线程处理是可伸缩的、容易响应的应用程序的关键。VB.NET编程支持加强的、多线程开发模型,它使开发者迅速拥有了开发多线程应用程序的能力。
◆VisualBasic .NET使用新的.NET框架组件类,它使建立多线程应用程序更容易。
◆记住尽管多线程能提高性能,但是每个线程有建立线程需要的附加内存和保持它运行需要的处理器时间的花消。
◆线程的属性和方法控制着线程间的交互操作,并且决定什么时候资源可以给运行的线程使用。
◆尽管多线程看起来带来了混乱,但是你可以使用同步技术控制正在运行的线程。
◆尽管多线程增加了应用程序的复杂性,但是它通过高效率分配可用资源提高了应用程序的可伸缩性。

使用本文讨论的技术,你可以开发和处理处理器密集型事务的专业应用程序。

转载于:https://www.cnblogs.com/leeyu2010/archive/2011/01/22/1941820.html

相关文章:

  • Ansible 自动化运维部署
  • IdHTTP处理HTTP 302遇到的问题
  • 如何进行数据库,比如ORACLE,SQL SERVER的逆向工程,将数据库导入到PowerDesigner中...
  • 微软首次针对Windows 7推杀毒软件 年内将推出
  • leetcode-02 两数相加
  • Converter Standalone 4.3问题解决方式
  • 概率论
  • 使用MASM08 - Win32汇编语言016
  • javascript压缩图片
  • Silver“.NET研究”light 游戏开发小技巧:透明背景的Silverlight程序
  • 在C#中,如何将一个int转换成一个byte array,又如何将一个byte array转换成一个int...
  • SpringBoot2.x集成WebSocket
  • Spinner示例
  • Silverlight杂记-本地程“.NET研究”序间的互通
  • C#.NET支付宝接口
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • Angularjs之国际化
  • Babel配置的不完全指南
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • Iterator 和 for...of 循环
  • Java 内存分配及垃圾回收机制初探
  • python 装饰器(一)
  • React 快速上手 - 07 前端路由 react-router
  • Vim 折腾记
  • Wamp集成环境 添加PHP的新版本
  • windows下mongoDB的环境配置
  • 分布式事物理论与实践
  • 官方解决所有 npm 全局安装权限问题
  • 机器学习 vs. 深度学习
  • 基于组件的设计工作流与界面抽象
  • 免费小说阅读小程序
  • 配置 PM2 实现代码自动发布
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 微信开源mars源码分析1—上层samples分析
  • 译自由幺半群
  • 中文输入法与React文本输入框的问题与解决方案
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • #HarmonyOS:基础语法
  • #mysql 8.0 踩坑日记
  • #pragma预处理命令
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (仿QQ聊天消息列表加载)wp7 listbox 列表项逐一加载的一种实现方式,以及加入渐显动画...
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (四)Android布局类型(线性布局LinearLayout)
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (算法)Game
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • (转)创业家杂志:UCWEB天使第一步
  • .CSS-hover 的解释
  • .NET 4.0中的泛型协变和反变
  • .NET Core 和 .NET Framework 中的 MEF2
  • .NET 命令行参数包含应用程序路径吗?