C# 多线程编程 ThreadStart ParameterizedThreadStart
原文地址:http://club.topsage.com/thread-657023-1-1.html
在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。
不带参数的启动方式
如果启动参数时无需其它额外的信息,可以使用ThreadStart来实例化Thread,如下面的代码:
View Code1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Threading; 5 6 namespace StartThread 7 { 8 class Program 9 {10 int interval = 200;11 static void Main(string[] args)12 {13 Program p = new Program();14 Thread nonParameterThread = new Thread(new ThreadStart(p.NonParameterRun));15 nonParameterThread.Start();16 }17 ///<summary>18 /// 不带参数的启动方法19 ///</summary>20 public void NonParameterRun()21 {22 for (int i = 0; i < 10; i++)23 {24 Console.WriteLine("系统当前时间毫秒值:"+DateTime.Now.Millisecond.ToString());25 Thread.Sleep(interval);//让线程暂停26 }27 }28 }
程序的运行效果我们不用运行也会知道,那就是在循环中将系统当前时间的毫秒部分输出出来,在每次输出之后会将当前线程暂停一下,直到10次之后运行完毕,终止线程的执行。
在上面的代码中我们是通过定义全局变量的方法来指定线程暂停间隔,按照这种方法,假如要运行10个线程,每个线程的暂停间隔不一样的话,就需要定义10个全局变量,虽然最终不影响系统的运行效果,但是总觉得不是太爽。
有没有比较简单一点的办法呢?有!那就是使用带参数的启动方法。
带参数的启动方法
如果要在实例化线程时要带一些参数,就不能用ThreadStart委托作为构造函数的参数来实例化Thread了,而要 ParameterizedThreadStart委托,和ThreadStart一样的是它也是线程启动时要执行的方法,和ThreadStart不同的是,它在实例化时可以用一个带有一个Object参数的方法作为构造函数的参数,而实例化ThreadStart时所用到的方法是没有参数的。
为什么是Object这样的参数呢?很简单,因为在.net中Object是所有类型的基类,用它可以表示Array(数组)、Interface(接口)、ValueType(值类型,如bool,byte,char,short,int,float,long,double等)、class(类)等.net中的类型。当然,这也意味着如果你要启动一个线程,给它传递一个int类型参数时,必须在 启动方法中进行相应的类型转换。
下面就是一个例子,在启动线程时指定了线程的暂停间隔,代码如下:
View Code1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Threading; 5 6 namespace StartThread 7 { 8 class Program 9 {10 int interval = 200;11 static void Main(string[] args)12 {13 Program p = new Program();14 15 Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));16 parameterThread.Name = "Thread A:";17 parameterThread.Start(30);18 }19 20 ///<summary>21 /// 带参数的启动方法22 ///</summary>23 ///<param name="ms">让线程在运行过程中的休眠间隔</param>24 public void ParameterRun(object ms)25 {26 int j = 10;27 int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常28 for (int i = 0; i < 10; i++)29 {30 Console.WriteLine(Thread.CurrentThread.Name+"系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());31 Thread.Sleep(j);//让线程暂停32 }33 }34 }35 }
在这个方法里,我们在启动线程时顺便指定了线程的暂停间隔,也就是这句:
parameterThread.Start(30);
线程启动时运行的方法是public void ParameterRun(object ms),这个值为30的int类型变量被装箱成object,所以在方法中还需要将它转换成int类型,这个可以通过拆箱或者其它办法解决。
假如我们要启动两个线程,每个线程的暂停间隔不一样,启动代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Threading; 5 6 namespace StartThread 7 { 8 class Program 9 {10 int interval = 200;11 static void Main(string[] args)12 {13 Program p = new Program();14 15 Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));16 parameterThread.Name = "Thread A:";17 parameterThread.Start(30);18 //启动第二个线程19 parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));20 parameterThread.Name = "Thread B:";21 parameterThread.Start(60);22 }23 24 ///<summary>25 /// 带参数的启动方法26 ///</summary>27 ///<param name="ms">让线程在运行过程中的休眠间隔</param>28 public void ParameterRun(object ms)29 {30 int j = 10;31 int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常32 for (int i = 0; i < 10; i++)33 {34 Console.WriteLine(Thread.CurrentThread.Name+"系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());35 Thread.Sleep(j);//让线程暂停36 }37 }38 }39 }
对上面的代码做一点说明,就是线程启动之后,线程的实例不必再存在,例如在上面的代码中我用的是同一个实例实例化了两个线程,并且这两个线程运行很正常。
继续探索
上面解决了一个问题,如果在启动线程时需要参数如何解决,如果针对上面的问题继续发掘,比如:在启动线程时不但要指定线程的暂停间隔,还需要指定循环次数(在上面的所有例子中都是执行10次的),这个问题该如何解决呢?
有两种办法可以解决:
首先可以继续在ParameterizedThreadStart这里做文章,因为这里可以使用一个Object类型的参数,那么可以通过数组或者一个类来解决(因为它们都是Object的子类)。我在做某个系统时确实采用数组处理过这种情况,这样就要求在线程启动方法中必须清楚知道数组中每个参数的用途,不是太方便。
这里说说重新定义一个实体类来解决的方法,代码如下。
View Code1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Threading; 5 6 namespace StartThread 7 { 8 class MyThreadParameter 9 {10 private int interval;11 private int loopCount;12 ///<summary>13 /// 循环次数14 ///</summary>15 public int LoopCount16 {17 get { return loopCount; }18 }19 20 ///<summary>21 /// 线程的暂停间隔22 ///</summary>23 public int Interval24 {25 get { return interval; }26 }27 ///<summary>28 /// 构造函数29 ///</summary>30 ///<param name="interval">线程的暂停间隔</param>31 ///<param name="loopCount">循环次数</param>32 public MyThreadParameter(int interval,int loopCount)33 {34 this.interval = interval;35 this.loopCount = loopCount;36 }37 }38 class Program39 {40 int interval = 200;41 static void Main(string[] args)42 {43 Program p = new Program();44 45 Thread parameterThread = new Thread(new ParameterizedThreadStart(p.MyParameterRun));46 parameterThread.Name = "Thread A:";47 MyThreadParameter paramter = new MyThreadParameter(50, 20);48 parameterThread.Start(paramter);49 }50 51 52 ///<summary>53 /// 带多个参数的启动方法54 ///</summary>55 ///<param name="ms">方法参数</param>56 public void MyParameterRun(object ms)57 {58 MyThreadParameter parameter = ms as MyThreadParameter;//类型转换59 if (parameter != null)60 {61 for (int i = 0; i < parameter.LoopCount; i++)62 {63 Console.WriteLine(Thread.CurrentThread.Name + "系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());64 Thread.Sleep(parameter.Interval);//让线程暂停65 }66 }67 }68 }69 }
第二种方法和上面方法有些相似,也是需要引入外部类,并且将Thread实例放在引入的类中,这种情况适合于在线程中处理的业务逻辑比较复杂的情况。在前不久处理的一个项目中我用过这种情况,它是用来实现双向数据传输的。
如果实现上面的效果,代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Threading; 5 6 namespace StartThread 7 { 8 class MyThreadParameter 9 {10 private int interval;11 private int loopCount;12 private Thread thread;13 14 ///<summary>15 /// 构造函数16 ///</summary>17 ///<param name="interval">线程的暂停间隔</param>18 ///<param name="loopCount">循环次数</param>19 public MyThreadParameter(int interval,int loopCount)20 {21 this.interval = interval;22 this.loopCount = loopCount;23 thread = new Thread(new ThreadStart(Run));24 }25 26 public void Start()27 {28 if (thread != null)29 {30 thread.Start();31 }32 }33 34 private void Run()35 {36 for (int i = 0; i < loopCount; i++)37 {38 Console.WriteLine("系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());39 Thread.Sleep(interval);//让线程暂停40 }41 }42 }43 class Program44 {45 static void Main(string[] args)46 {47 MyThreadParameter parameterThread = new MyThreadParameter(30, 50);48 parameterThread.Start();49 }50 51 }52 }
上面的代码的运行效果和前面的代码运行效果类似,只不过是将业务处理代码放在一个单独的类MyThreadParameter中,使得MyThreadParameter看起来也像一个Thread,实际上维护的还是其内部的Thread,在一些大型系统中这样做的好处是便于维护。
总结:在本篇主要讲述如何启动线程的问题,在启动时可能会遇到无需参数、需要多个参数的情况,在这里讲述了如何解决这些问题的思路。在.net类库中虽然存在着庞大的类库,但是并不是总会有合适的类来解决我们所遇到的问题,但是只要肯动脑筋总会想到合适的办法。
转载于:https://www.cnblogs.com/xiaoyaozhe/archive/2011/11/10/2244110.html
C# 多线程编程 ThreadStart ParameterizedThreadStart相关推荐
- .Net开发中的多线程编程总结
微软.Net开发中的多线程编程进行一个简单的总结,相信对大家会有所帮助的.下面就具体来看看: 不需要传递参数,也不需要返回参数 我们知道启动一个线程最直观的办法是使用Thread类,具体步骤如下: T ...
- 微软.Net开发中的多线程编程总结
不需要传递参数,也不需要返回参数 我们知道启动一个线程最直观的办法是使用Thread类,具体步骤如下: ThreadStart threadStart=new ThreadStart(Calculat ...
- 浅述WinForm多线程编程与Control.Invoke的应用
在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在WinForm开发中必不可 ...
- C#多线程编程实战(二)
1.1 简介 为了防止一个应用程序控制CPU而导致其他应用程序和操作系统本身永远被挂起这一可能情况,操作系统不得不使用某种方式将物理计算分割为一些虚拟的进程,并给予每个执行程序一定量的计算能力.此外操 ...
- Linux下不使用qt自带sleep,Linux下Qt多线程编程
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 作者:武汉华嵌嵌入式培训中心 技术部 以下和大家分享Linux平台下Qt两种多线程编程的方式: 1.使用Linux平台下的线程函数.以下是给出的代码片段: ...
- C#如何进行多线程编程
C#如何进行多线程编程 由于多线程编程非常复杂,这个小例子只能算是一个入门线的知识点吧 首先建一个应用程序项目,命名为ThreadExample,在窗体上放一个文本框(textBox1) ,一个标签( ...
- 多线程编程实战(一)
为了快速处理大量的任务,多线程编程必不可少,所以最近也开始研究多线程方面的东西了.网上有不少资料可以参考,自己从实例入手,总结了一些东西,把它记录下来,方便自己日后查阅,也方便后来人.现在的编程语言, ...
- .NET多线程编程入门
在.NET多线程编程这个系列我们讲一起来探讨多线程编程的各个方面.首先我将在本篇文章的开始向大家介绍多线程的有关概念以及多线程编程的基础知识;在接下来的文章中,我将逐一讲述.NET平台上多线程编程的知 ...
- C#多线程编程介绍——使用thread、threadpool、timer
C#多线程编程介绍--使用thread.threadpool.timer 在system.threading 命名空间提供一些使得能进行多线程编程的类和接口,其中线程的创建有以下三种方法:thread ...
最新文章
- 零基础学python爬虫-零基础学习python_爬虫(53课)
- 中国高校毕业生即将加速蓝领化
- Spring boot转发请求
- 电子科大计算机大类包括专业,电子科技大学a类学科有哪些?附电子科大a类学科名单...
- Nginx开启SSL支持实例配置
- MFC添加自定义消息及重写消息过程
- python列表数据类型一致_python笔记--数据类型--列表
- python中的一个现象,db.commit和db.commit()
- python rpc_对python调用RPC接口的实例详解
- Linux汇编调试器EDB
- 解决IE8在vs2005下不能调试的问题.
- 【SICP练习】31 练习1.37
- 【2016Esri全球用户大会主题亮点】GIS is Getting Smarter——JACK主题演讲权威解读
- 计算机flash教案,flash教学计划
- 【备忘】hive 调优
- spss python_ARIMA模型 - [SPSS Python]
- tp link拨号失败 服务器无响应,【求救】K2提示“等待PPP客户端连接”拨号失败...
- arcgis for Android 100.3.0 加载shp数据以及操作
- 好好吃饭,才是最大的教养
- 【Chrome】解决浏览器萤幕画面模糊字体不清楚方法