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

线程启动 [转]

转自:http://blog.csdn.net/zhoufoxcn/article/details/4402999

在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。
 不带参数的启动方式
 如果启动参数时无需其它额外的信息,可以使用ThreadStart来实例化Thread,如下面的代码:

using System;  
    using System.Collections.Generic;  
    using System.Text;  
    using System.Threading;  
      
    namespace StartThread  
    {  
        class Program  
        {  
            int interval = 200;  
            static void Main(string[] args)  
            {  
                Program p = new Program();  
                Thread nonParameterThread = new Thread(new ThreadStart(p.NonParameterRun));  
                nonParameterThread.Start();  
            }  
            /// <summary>   
            /// 不带参数的启动方法   
            /// </summary>   
            public void NonParameterRun()  
            {  
                for (int i = 0; i < 10; i++)  
                {  
                    Console.WriteLine("系统当前时间毫秒值:"+DateTime.Now.Millisecond.ToString());  
                    Thread.Sleep(interval);//让线程暂停   
                }  
        }  
    }  

 

程序的运行效果我们不用运行也会知道,那就是在循环中将系统当前时间的毫秒部分输出出来,在每次输出之后会将当前线程暂停一下,直到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类型参数时,必须在启动方法中进行相应的类型转换。
 下面就是一个例子,在启动线程时指定了线程的暂停间隔,代码如下:

using System;  
    using System.Collections.Generic;  
    using System.Text;  
    using System.Threading;  
      
    namespace StartThread  
    {  
        class Program  
        {  
            int interval = 200;  
            static void Main(string[] args)  
            {  
                Program p = new Program();  
      
                Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));  
                parameterThread.Name = "Thread A:";  
                parameterThread.Start(30);  
            }  
         
            /// <summary>   
            /// 带参数的启动方法   
            /// </summary>   
            /// <param name="ms">让线程在运行过程中的休眠间隔</param>   
            public void ParameterRun(object ms)  
            {  
                int j = 10;  
                int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常   
                for (int i = 0; i < 10; i++)  
                {  
                    Console.WriteLine(Thread.CurrentThread.Name+"系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());  
                    Thread.Sleep(j);//让线程暂停   
                }  
            }  
        }  
    }  

 

在这个方法里,我们在启动线程时顺便指定了线程的暂停间隔,也就是这句:
 parameterThread.Start(30);
 线程启动时运行的方法是public void ParameterRun(object ms),这个值为30的int类型变量被装箱成object,所以在方法中还需要将它转换成int类型,这个可以通过拆箱或者其它办法解决。
 假如我们要启动两个线程,每个线程的暂停间隔不一样,启动代码如下:
using System;  
    using System.Collections.Generic;  
    using System.Text;  
    using System.Threading;  
      
    namespace StartThread  
    {  
        class Program  
        {  
            int interval = 200;  
            static void Main(string[] args)  
            {  
                Program p = new Program();  
      
                Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));  
                parameterThread.Name = "Thread A:";  
                parameterThread.Start(30);  
                //启动第二个线程   
                parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));  
                parameterThread.Name = "Thread B:";  
                parameterThread.Start(60);  
            }  
         
            /// <summary>   
            /// 带参数的启动方法   
            /// </summary>   
            /// <param name="ms">让线程在运行过程中的休眠间隔</param>   
            public void ParameterRun(object ms)  
            {  
                int j = 10;  
                int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常   
                for (int i = 0; i < 10; i++)  
                {  
                    Console.WriteLine(Thread.CurrentThread.Name+"系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());  
                    Thread.Sleep(j);//让线程暂停   
                }  
            }  
        }  
    }  

 

对上面的代码做一点说明, 就是线程启动之后,线程的实例不必再存在,例如在上面的代码中我用的是同一个实例实例化了两个线程,并且这两个线程运行很正常。
 
  继续探索
 上面解决了一个问题,如果在启动线程时需要参数如何解决,如果针对上面的问题继续发掘,比如:在启动线程时不但要指定线程的暂停间隔,还需要指定循环次数(在上面的所有例子中都是执行10次的),这个问题该如何解决呢?
 有两种办法可以解决:
 首先可以继续在ParameterizedThreadStart这里做文章,因为这里可以使用一个Object类型的参数,那么可以通过数组或者一个类来解决(因为它们都是Object的子类)。我在做某个系统时确实采用数组处理过这种情况,这样就要求在线程启动方法中必须清楚知道数组中每个参数的用途,不是太方便。
 这里说说重新定义一个实体类来解决的方法,代码如下。
using System;  
    using System.Collections.Generic;  
    using System.Text;  
    using System.Threading;  
      
    namespace StartThread  
    {  
        class MyThreadParameter  
        {  
            private int interval;  
            private int loopCount;  
            /// <summary>   
            /// 循环次数   
            /// </summary>   
            public int LoopCount  
            {  
                get { return loopCount; }  
            }  
          
            /// <summary>   
            /// 线程的暂停间隔   
            /// </summary>   
            public int Interval  
            {  
                get { return interval; }  
            }  
            /// <summary>   
            /// 构造函数   
            /// </summary>   
            /// <param name="interval">线程的暂停间隔</param>   
            /// <param name="loopCount">循环次数</param>   
            public MyThreadParameter(int interval,int loopCount)  
            {  
                this.interval = interval;  
                this.loopCount = loopCount;  
            }  
        }  
        class Program  
        {  
            int interval = 200;  
            static void Main(string[] args)  
            {  
                Program p = new Program();  
      
                Thread parameterThread = new Thread(new ParameterizedThreadStart(p.MyParameterRun));  
                parameterThread.Name = "Thread A:";  
                MyThreadParameter paramter = new MyThreadParameter(50, 20);  
                parameterThread.Start(paramter);  
            }  
       
      
            /// <summary>   
            /// 带多个参数的启动方法   
            /// </summary>   
            /// <param name="ms">方法参数</param>   
            public void MyParameterRun(object ms)  
            {  
                MyThreadParameter parameter = ms as MyThreadParameter;//类型转换   
                if (parameter != null)  
                {  
                    for (int i = 0; i < parameter.LoopCount; i++)  
                    {  
                        Console.WriteLine(Thread.CurrentThread.Name + "系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());  
                        Thread.Sleep(parameter.Interval);//让线程暂停   
                    }  
                }  
            }  
        }  
    }  

 

第二种方法和上面方法有些相似,也是需要引入外部类,并且将Thread实例放在引入的类中,这种情况适合于在线程中处理的业务逻辑比较复杂的情况。在前不久处理的一个项目中我用过这种情况,它是用来实现双向数据传输的。
 如果实现上面的效果,代码如下:

using System;  
    using System.Collections.Generic;  
    using System.Text;  
    using System.Threading;  
      
    namespace StartThread  
    {  
        class MyThreadParameter  
        {  
            private int interval;  
            private int loopCount;  
            private Thread thread;  
              
        /// <summary>   
        /// 构造函数   
        /// </summary>   
            /// <param name="interval">线程的暂停间隔</param>   
            /// <param name="loopCount">循环次数</param>   
            public MyThreadParameter(int interval,int loopCount)  
            {  
                this.interval = interval;  
                this.loopCount = loopCount;  
                thread = new Thread(new ThreadStart(Run));  
            }  
      
            public void Start()  
            {  
                if (thread != null)  
                {  
                    thread.Start();  
                }  
            }  
      
            private void Run()  
            {  
                for (int i = 0; i < loopCount; i++)  
                {  
                    Console.WriteLine("系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());  
                    Thread.Sleep(interval);//让线程暂停   
                }  
            }  
        }  
        class Program  
        {  
            static void Main(string[] args)  
            {  
                MyThreadParameter parameterThread = new MyThreadParameter(30, 50);  
                parameterThread.Start();  
            }  
      
        }  
    }  

 

using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace StartThread { class MyThreadParameter { private int interval; private int loopCount; private Thread thread; /// <summary> /// 构造函数 /// </summary> /// <param name="interval">线程的暂停间隔</param> /// <param name="loopCount">循环次数</param> public MyThreadParameter(int interval,int loopCount) { this.interval = interval; this.loopCount = loopCount; thread = new Thread(new ThreadStart(Run)); } public void Start() { if (thread != null) { thread.Start(); } } private void Run() { for (int i = 0; i < loopCount; i++) { Console.WriteLine("系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString()); Thread.Sleep(interval);//让线程暂停 } } } class Program { static void Main(string[] args) { MyThreadParameter parameterThread = new MyThreadParameter(30, 50); parameterThread.Start(); } } }

 

上面的代码的运行效果和前面的代码运行效果类似,只不过是将业务处理代码放在一个单独的类MyThreadParameter中,使得MyThreadParameter看起来也像一个Thread,实际上维护的还是其内部的Thread,在一些大型系统中这样做的好处是便于维护。
 
 总结:在本篇主要讲述如何启动线程的问题,在启动时可能会遇到无需参数、需要多个参数的情况,在这里讲述了如何解决这些问题的思路。在.net类库中虽然存在着庞大的类库,但是并不是总会有合适的类来解决我们所遇到的问题,但是只要肯动脑筋总会想到合适的办法。

转载于:https://www.cnblogs.com/Jenny90/archive/2013/04/22/3035389.html

相关文章:

  • PSP Skype 使用国内卡
  • php.ini 中文版[转]
  • 使用StyleCop进行代码审查
  • wcf服务代理层添加wcf服务异步代理
  • 检测是否支持position:fixed
  • [译]学习IPython进行交互式计算和数据可视化(三)
  • 【PSY】 [歌詞] 父親
  • 一步一步学Remoting之三:复杂对象
  • linux下查看磁盘空间
  • Greenplum table 之 appendonly的列存储表
  • 云计算实验(二)Hadoop 练习
  • 云计算实验(三)CloudSim练习
  • 信息安全实验一:DES分组密码算法 2019.03.21
  • 信息安全实验二:分组密码工作模式 2019.04.15
  • 信息安全实验三:求模逆算法 2019.04.18
  • 【Amaple教程】5. 插件
  • 【RocksDB】TransactionDB源码分析
  • Create React App 使用
  • JavaScript 基本功--面试宝典
  • Java多态
  • JAVA之继承和多态
  • react-native 安卓真机环境搭建
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • 初识 beanstalkd
  • 从零开始在ubuntu上搭建node开发环境
  • 解决iview多表头动态更改列元素发生的错误
  • 开源SQL-on-Hadoop系统一览
  • 一、python与pycharm的安装
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • FaaS 的简单实践
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​卜东波研究员:高观点下的少儿计算思维
  • ​学习一下,什么是预包装食品?​
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • (06)Hive——正则表达式
  • (1)SpringCloud 整合Python
  • (python)数据结构---字典
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (转)c++ std::pair 与 std::make
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .dwp和.webpart的区别
  • .NET Framework与.NET Framework SDK有什么不同?
  • .net 程序发生了一个不可捕获的异常
  • .net对接阿里云CSB服务
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • .NET设计模式(7):创建型模式专题总结(Creational Pattern)
  • .net最好用的JSON类Newtonsoft.Json获取多级数据SelectToken
  • @31省区市高考时间表来了,祝考试成功
  • @Autowired注解的实现原理
  • @KafkaListener注解详解(一)| 常用参数详解
  • [ 云计算 | AWS 实践 ] Java 如何重命名 Amazon S3 中的文件和文件夹