教程学院
图像设计 多媒体类 机械制图 办公软件 操作系统 系统编程 网站编程 网页制作 数据库类 网络路由 网络工程 网络安全 考试认证
酷网学院
CAD
AutoCad Cam350 ProEngineer GCcam MATLAB Unigraphics SolidWorks CAXA Solid3000 Cimatron EdgeCAM
系统
安全 防火墙 病毒 WinXP Win2003 Vista
数据库
编程
网络
  网站导航: 库库中文网 · 系统编程教程 · C#语言 · C# .NET  

在.NET客户端程序里面运用多线程

教程推荐
『在.NET客户端程序里面运用多线程』如果文章有大量图片,显示会较慢,请等待图片下载完成
 
点击数: 更新时间:2005-8-9 
}

   在Figure 4 的末尾处有一个EnableControls的新方法,它允许或禁止窗体上的文本框和按钮控件。在Figure 4 的开始我加入了一个EnableControls调用,在后台响铃操作排队等候之前立即禁止文本框和按钮。到这里线程的同步工作已经完成了一半,因为禁止了用户交互,所以用户不能引发更多的后台冲突操作。在Figure 4 的末尾你将看到一个名为BooleanCallback的委托类型被定义,其签名是同EnableControls方法兼容的。在那个定义之前,一个名为EnableControls的委托域被定义(见例子),它引用了该窗体的EnableControls方法。这个委托域在代码的开始处被分配。

   你也将看到一个来自主线程的回调,该主线程为窗体和其控件拥有和提取消息。这个调用通过向EnableControls传递一个true参数来使能控件。这通过后台线程调用窗体的Invoke方法来完成,当其一旦完成其长响铃操时。代码传送的委托引用EnableControls去Invoke,该方法的参数带有一个对象数组。Invoke方法是线程间通信的一个非常灵活的方式,特别是对于Windows Forms类库中的窗口或窗体。在这个例子中,Invoke被用来告诉主GUI线程通过调用EnableControls方法重新使能窗体上的控件。

   Figure 4 中的CorrectMultiThreadedForm.cs的变化实现了我早先的建议――当响铃操作在执行时你不想运行,就禁止引发响铃操作的用户交互部分。当操作完成时,告诉主线程重新使能被禁止的部分。对Invoke的调用是唯一的,这一点应该注意。

   Invoke方法在 System.Windows.Forms.Controls类型中定义,包含Form类型让类库中的所有派生控件都可使用该方法。Invoke方法的目的是配置了一个从任何线程对为窗体或控件实现消息提取线程的调用。

   当访问控件派生类时,包括Form类,从提取控件消息的线程来看你必须这样做。这在单线程的应用程序中是很自然的事情。但是当你从线程池中使用多线程时,要避免从后台线程中调用用户交互对象的方法和属性是很重要的。相反,你必须使用控件的Invoke方法间接的访问它们。Invoke是控件中很少见的一个可以安全的从任何线程中调用的方法,因为它是用Win32的PostMessage API实现的。

   使用Control.Invoke方法进行线程间的通信有点复杂。但是一旦你熟悉了这个过程,你就有了在你的客户端程序中实现多线程目标的工具。本栏目的剩余部分将覆盖其它一些细节,但是Figure 4 中的CorrectMultiThreadedForm.cs应用程序是一个完整的解决办法:当执行任意长的操作时仍然能够响应用户的其它操作。尽管大多数的用户交互被禁止,但用户仍然可以重新配置和调整窗口,也可以关闭程序。然而,用户不能任意使用程序的异步行为。这个小细节能够让你对你的程序保持自信心。

   在我的第一个线程同步程序中,没有使用任何传统的线程结构,例如互斥或信号量,似乎一钱不值。然而,我却使用了禁止控件的最普通的方法。
细节-实现一个取消按钮

   有时你想为你的用户提供一种取消长操作的方法。你所需要的就是你的主线程同后台线程之间的一些通信方法,通知后台线程操作不再被需要,可以停止。System.Threading名字空间为这个方法提供了一个类:AutoResetEvent。

   AutoResetEvent是线程间通信的一种简单机制。一个AutoResetEvent对象可以有两种状态中的一个:有信号的和无信号的。当你创建一个AutoResetEvent实例时,你可以通过构造函数的参数来决定其初始状态。然后感知该对象的线程通过检查AutoResetEvent对象的状态,或者用    AutoResetEvent对象的Set或Reset方法调整其状态,进行相互通信。

   在某种程度上AutoResetEvent很像一个布尔类型,但是它提供的特征使其更适合于在线程间进行通信。这样的一个例子就是它有这种能力:一个线程可以有效的等待直到一个AutoResetEvent对象从一个无信号的状态变为有信号的状态。它是通过在该对象上调用WaitOne实现的。任何一个线程对一个无信号的AutoResetEvent对象调用了WaitOne,就会被有效的阻塞直到其它线程使该对象有信号。使用布尔变量线程必须在一个循环中登记该变量,这是无效率的。一般来说没有必要使用Reset来使一个AutoResetEvent变为无信号,因为当其它线程感知到该对象为有信号时,它会被立即自动的设为无信号的。

   现在你需要一种让你的后台线程无阻塞的测试AutoResetEvent对象的方法,你会有许多工具实现线程的取消。为了完成这些,调用带有WaitOne的重载窗体并指出一个零毫秒的超出时间,以零毫秒为超出时间的WaitOne会立即返回,而不管AutoResetEvent对象的状态是否为有信号。如果返回值为true,这个对象是有信号的;否则由于时间超出而返回。

   我们整理一下实现取消的特点。如果你想实现一个取消按钮,它能够取消后台线程中的一个长操作,按照以下步骤:

在你的窗体上加入AutoResetEvent域类型

   通过在AutoResetEvent的构造函数中传入false参数,设置该对象初始状态为无信号的。 接着在你的窗体上保 存该对象的引用域,这是为了能够在窗体的整个生命周期内可以对后台线程的后台操作实现取消操作。

   在你窗体上加入一个取消按钮。

   在取消按钮的Click事件处理器中,通过调用AutoResetEvent对象的Set方法使其有信号。

   同时,在你的后台线程的逻辑中周期性地在AutoResetEvent对象上调用WaitOne来检查用户是否取消了。

if(cancelEvent.WaitOne(0, false)){
// cancel operation
}

   你必须记住使用零毫秒参数,这样可以避免在后台线程操作中不必要的停顿。

   如果用户取消了操作,通过主线程AutoResetEvent会被设为有信号的。 当WaitOne返回true时你的后台线程会 得到警告,并停止操作。同时在后台线程中由于调用了WaitOne该事件会被自动的置为无信号状态。

   为了能够看到取消长操作窗体的例子,你可以下载CancelableForm.cs文件。这个代码是一个完整的程序,它与Figure 4 中的CorrectMultiThreadedForm.cs只有稍微的不同。

   注意在CancelableForm.cs也采用了比较高级的用法Control.Invoke, 在那里EnableControls方法被设计用来调用它自己如果当它被一个错误的线程所调用时。在它使用窗体上的任何GUI对象的方法或属性时要先做这个检查。 这样能够使得EnableControls能够从任何线程中直接安全的调用,在方法的实现中有效的隐藏了Invoke调用的复杂性。这些可以使应用程序更加有维护性。注意在这个例子中同样使用了Control.BeginInvoke, 它是Control.Invoke的异步版本。

   你也许注意到取消的逻辑依赖于后台线程通过WaitOne调用周期性的取消检查的能力。 但是如果正在讨论的问题不能被取消怎么办?如果后台操作是一个单个调用,像DataAdapter.Fill,它会花很长时间?有时会有解决办法的,但并不总是。

   如果你的长操作根本不能取消,你可以使用一个伪取消的方法来完成你的操作,但在你的程序中不要影响你的操作结果。这不是技术上的取消操作,它把一个可忍受的操作帮定到一个线程池中,但这是在某种情况下的一种折中办法。如果你实现了类似的解决办法,你应该从你的取消按钮事件处理器中直接使能你已禁止的UI元素,而不要还依赖于被绑定的后台线程通过Invoke调用使能你的控件。同样重要的使设计你的后台操作线程,当其返回时测试一下它是否被取消,以便它不影响现在被取消的操作的结果。

   这种长操作取消是比较高级的方法,它只在某些情况下才可行。例如,数据库查询的伪

上一页  [1] [2] [3] [4] [5] 下一页

】【关闭窗口
  上一页:
  下一页:
 ·网站导航: 库库中文网 · 系统编程教程 · C#语言 · C# .NET
C# .NET:相关文章
C# .NET点击榜
推荐教程C# 3.0新特性初步研究 Part6:运
推荐教程C# 3.0新特性初步研究 Part5:匿
推荐教程C# 3.0新特性初步研究 Part4:运
推荐教程C# 3.0新特性初步研究 Part3:运
推荐教程C# 3.0新特性初步研究 Part2:运
推荐教程C# 3.0新特性初步研究 Part1:运
推荐教程ADO.NET地设计场景及传统ADO地处
推荐教程通过Visual C#.NET建一个DTS任务
推荐教程VC# .Net里面运用Crystal Repor
推荐教程C# .Net里面地类型转换(1)
PHOTOSHOP - 基础教程 抠图专题 蒙版专题 3DsMax 基础 设计实例 Maya设计实例
3D设计教程
advertisement
关于站点 - 广告服务 - 联系我们 - 版权隐私 - 免责声明 - 合作伙伴 - 程序支持 - 网站地图 - 返回顶部
网站文本地图
版权所有:库库中文 2005-2007 欢迎各种媒体转载我们的原创作品[转载请注明出处]
copyright ? 2005-2008 www.QQGB.com online services. all rights reserved. 蜀ICP备05015578
Optimized for 1024x768 to Firefox,Opera and MS-IE6. Site powered by EQL. 电脑硬件 电脑知识 教程学习
红盾
热爱电脑,热爱生活
拥有电脑,拥有生命
让我们享受拥有电脑的时光