今天图老师小编给大家精心推荐个Visual C#中使用线程教程,一起来看看过程究竟如何进行吧!喜欢还请点个赞哦~
【 tulaoshi.com - 编程语言 】
摘要:本文论述了各种模式的线程(单线程、单元线程和自由线程)以及每种模式的使用方法。同时,还提供了一个使用线程的 C# 语言代码示例,以帮助您编写使用线程的应用程序。本文还讨论了多线程代码中的一些重要问题。
简介
编写多线程 Microsoft® 消息队列 (MSMQ) 触发器应用程序向来是一件让人畏惧的事情。不过,.NET 框架线程和消息类的出现使这项工作变得比以前容易了。这些类允许您使用任何适用于 .NET 框架的语言来编写多线程应用程序。以前,像 Microsoft Visual Basic® 之类的工具对线程的支持十分有限。因此不得不使用 C++ 来编写多线程代码,通过 Visual Basic 构建由多个过程或 ActiveX DLL 组成的解决方案(这种解决方案一点也不理想),或者干脆完全放弃多线程。使用 .NET 框架,您可以构建各种多线程应用程序,而不用考虑选择使用哪种语言。
本文将逐步介绍构建侦听并处理来自 Microsoft 消息队列的多线程应用程序的过程。本文将着重讨论两个名称空间 System.Threading 和 System.Messaging。示例代码是用 C# 语言编写的,但您可以轻松地将其转换为您所使用的语言。
(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/) 线程背景在 Win32 环境中,线程有三种基本模式:单线程、单元线程和自由线程。
单线程您最初编写的某些应用程序很可能是单线程应用程序,仅包含与应用程序进程对应的线程。进程可以被定义为应用程序的实例,拥有该应用程序的内存空间。大多数 Windows 应用程序都是单线程的,即用一个线程完成所有工作。
单元线程单元线程是一种稍微复杂的线程模式。标记用于单元线程的代码可以在其自己的线程中执行,并限制在自己的单元中。线程可以被定义为进程所拥有的实体。处理时将调度该进程。在单元线程模式中,所有线程都在主应用程序内存中各自的子段范围内运行。此模式允许多个代码实例同时但独立地运行。例如,在 .NET 之前,Visual Basic 仅限于创建单元线程组件和应用程序。
自由线程自由线程是最复杂的线程模式。在自由线程模式中,多个线程可以同时调用相同的方法和组件。与单元线程不同,自由线程不会被限制在独立的内存空间。当应用程序必须进行大量相似而又独立的数学计算时,您可能需要使用自由线程。在这种情况下,您需要生成多个线程使用相同的代码示例来执行计算。可能 C++ 开发人员是仅有的编写过自由线程应用程序的应用程序开发人员,因为像 Visual Basic 6.0 这样的语言几乎不可能编写自由线程应用程序。
使用线程模式为了使您对线程模式有一定的概念,我们可以将其想象为从一所屋子搬到另一所屋子。如果您采用单线程方法,则需要您自己完成从打包到扛箱子再到拆包的所有工作。如果您使用单元线程模式,则表示您邀请了好朋友来帮忙。每个朋友在一个单独的房间里工作,并且不能帮助在其他房间工作的人。他们各自负责自己的空间和空间内的物品搬运。如果您采用自由线程方法,您仍然邀请相同的朋友来帮忙,但是所有朋友可以随时在任何一个房间工作,共同打包物品。与此类似,您的房子就是运行所有线程的进程,每个朋友都是一个代码实例,搬运的物品为应用程序的资源和变量。
本示例解释了不同线程模式的优点和缺点。单元线程比单线程要快,因为有多个组件实例在工作。在某些情况下,自由线程比单元线程更快更有效,这是因为所有事情同时发生,并且可以共享所有资源。但是,当多线程更改共享资源时,这可能会出现问题。假设一个人开始使用箱子打包厨房用具,此时另一个朋友进来了,要使用同一个箱子打包浴室的东西。第一个朋友在箱子上贴上了厨房用具,另一个朋友用洗漱用品标签覆盖了原标签。结果,当您拆包时,就会发生将厨房用品搬到浴室的情况。
示例应用程序
第一步是要检查示例应用程序的设计。应用程序将生成多个线程,每个线程都侦听来自 MSMQ 队列的消息。本示例使用两个类,主 Form 类和自定义 MQListen 类。Form 类将处理用户界面并创建,管理和破坏辅助线程。MQListen 类包含所有代码,包括辅助线程运行所需的消息队列因素。
准备应用程序
要启动应用程序,请打开 Visual Studio .NET 并创建一个名为 MultiThreadedMQListener 的新 C# Windows 应用程序。打开窗体的属性,将其命名为 QueueListenerForm。画出初始窗体后,将两个标签、两个按钮、一个状态栏和两个文本框拖放到窗体上。将第一个文本框命名为 Server,第二个文本框命名为 Queue。将第一个按钮命名为 StartListening,第二个按钮命名为 StopListening。可以保留状态栏的默认名称 statusBar1。 下一步,单击 Project(项目)菜单并单击 Add Reference(添加引用),以向 System.Messaging 名称空间添加一个引用。在 .NET 组件列表中找到并选择 System.Messaging.Dll。名称空间包含与 MSMQ 队列通信所使用的类。 下一步,单击 File(文件)菜单,然后单击 Add New Item(添加新项),以在项目中添加一个新类。选择 Class(类)模板并将其命名为 MQListen。在类的顶部添加下列 using 语句:// C#
using System.Threading;
using System.Messaging;
System.Threading 名称空间允许您访问所有必要的线程功能,在本例中,您可以访问 Thread 类和 ThreadInterruptException 构造函数。该名称空间还包括许多其他高级功能,本文不作详细讨论。System.Messaging 名称空间允许您访问 MSMQ 功能,包括向队列发送消息和接收队列消息。在本例中,您将使用 MessageQueue 类来接收消息。还必须在主窗体代码中添加 using System.Threading。
所有引用就位后,您就可以开始编写代码了。
辅助线程
首先需要构建封装所有线程工作的 MQListen 类。将下列代码插入 MQListen 中。
(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)// C#public class MQListen{private string m_MachineName;private string m_QueueName;// 构造函数接收必要的队列信息。public MQListen(string MachineName, string QueueName){m_MachineName = MachineName;m_QueueName = QueueName;}// 每个线程用来侦听 MQ 消息的一种唯一方法public void Listen(){// 创建一个 MessageQueue 对象。System.Messaging.MessageQueue MQ = newSystem.Messaging.MessageQueue();// 设置 MessageQueue 对象的路径属性。MQ.Path = m_MachineName + "private$" + m_QueueName;// 创建一个 Message 对象。System.Messaging.Message Message = newSystem.Messaging.Message();// 重复上述步骤,直到收到中断。while (true){try{// 休眠以在中断发出时捕捉中断。System.Threading.Thread.Sleep(100);// 将 Message 对象设置为与接收函数的结果相等。// 持续时间(天、小时、分钟、秒)。Message = MQ.Receive(new TimeSpan(0, 0, 0, 1));// 显示已接收消息的标签System.Windows.Forms.MessageBox.Show(" Label: " + Message.Label);}catch (ThreadInterruptedException e){// 从主线程捕捉 ThreadInterrupt 并退出。Console.WriteLine("Exiting Thread");Message.Dispose();MQ.Dispose();break;}catch (Exception GenericException){// 捕捉接收过程中抛出的所有异常。Console.WriteLine(GenericException.Message);}}}}
代码讨论
MQListen 类包含一个不同于构造函数的函数。该函数封装每个辅助线程要执行的所有工作。在主线程中,您向线程构造函数传递一个对此函数的引用,以便在启动线程时执行该函数。
Listen 所做的第一件事情是设置一个消息队列对象。MessageQueue 构造函数通过三种实现进行重载。第一种实现使用两个参数:一个字符串参数,指定侦听队列的位置;一个布尔值参数,指示是否为访问队列的第一个应用程序赋予独占读取队列的权限。第二种实现只使用队列路径参数,第三种实现不使用参数。为了简便起见,您可以使用第三种实现,在下一行分配路径。
如果您引用了队列,则必须创建一个消息对象。消息构造函数也有三种实现方式。如果您想将消息写入队列,则可以使用前两种实现。这两种实现采用两个对象:一个是位于消息正文中的对象;一个是定义如何将对象序列化到消息正文的 IMessageFormatter 对象。在本例中,您将从队列中读取数据,以初始化空的消息对象。
初始化对象后,您需要输入执行所有工作的主循环。然后,当主线程调用 Interrupt 终止这些线程时,则只有在线程处于等待、睡眠或连接状态下才会被中断。如果没有处于上述三种状态,则要等到下次进入这三种状态中的一种时才会被中断。要确保辅助线程进入等待、睡眠或连接状态,请调用位于 System.Threading 名称空间的 Sleep 方法。对于使用过 Windows API 睡眠函数的 C++ 和 Visual Basic 开发人员而言,Sleep 方法并不陌生。它只使用一个参数:线程处于睡眠状态的毫秒数。如果您从未调用过 Sleep,辅助线程将永远不会进入可以接收中断请求的状态,而会无限制地继续下去,除非您手动关闭进程。
来源:http://www.tulaoshi.com/n/20160219/1613697.html
看过《Visual C#中使用线程》的人还看了以下文章 更多>>