C# 多线程编程 ThreadStart ParameterizedThreadStart
- 原文地址:http://club.topsage.com/thread-657023-1-1.html
- 在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。
- 不带参数的启动方式
- 如果启动参数时无需其它额外的信息,可以使用ThreadStart来实例化Thread,如下面的代码:
- 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 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类型参数时,必须在 启动方法中进行相应的类型转换。
- 下面就是一个例子,在启动线程时指定了线程的暂停间隔,代码如下:
- 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
- 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的子类)。我在做某个系统时确实采用数组处理过这种情况,这样就要求在线程启动方法中必须清楚知道数组中每个参数的用途,不是太方便。
- 这里说说重新定义一个实体类来解决的方法,代码如下。
- 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 ///<summary>
- 13 /// 循环次数
- 14 ///</summary>
- 15 public int LoopCount
- 16 {
- 17 get { return loopCount; }
- 18 }
- 19
- 20 ///<summary>
- 21 /// 线程的暂停间隔
- 22 ///</summary>
- 23 public int Interval
- 24 {
- 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 Program
- 39 {
- 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 Program
- 44 {
- 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类库中虽然存在着庞大的类库,但是并不是总会有合适的类来解决我们所遇到的问题,但是只要肯动脑筋总会想到合适的办法。
C# 多线程编程 ThreadStart ParameterizedThreadStart的更多相关文章
- 多线程之 ThreadStart 和 ParameterizedThreadStart 委托
先看微软如何给出的方法使用,如下查看,我们发现,如下两个委托,分别对应带参数创建线程 和 不带参数创建线程. 下列 委托 方法不带参数 ThreadStart namespace System.Thr ...
- 浅述WinForm多线程编程与Control.Invoke的应用
VS2008.C#3.0在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在W ...
- C#多线程编程总结
VS2008.C#3.0在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在W ...
- C#多线程编程笔记
在开发中经常有遇到因为程序执行的时间过长,而造成程序假死的情况,这是因为我们的程序是同步执行的,当执行到需要长时间的操作时,程序就会等待当前的操作完成,从而造成程序假死.C#的异步与多线程就是为了解决 ...
- C#多线程编程实战(二)
1.1 简介 为了防止一个应用程序控制CPU而导致其他应用程序和操作系统本身永远被挂起这一可能情况,操作系统不得不使用某种方式将物理计算分割为一些虚拟的进程,并给予每个执行程序一定量的计算能力.此外操 ...
- C# 多线程编程,传参,接受返回值
C# 多线程编程,传参,接受返回值 今天将多线程的知识有回顾了下,总结了几点: 新建一个线程(无参数,无返回值) Thread th = new Thread(new ThreadStart(Prin ...
- WinForm多线程编程与Control.Invoke的应用浅谈
在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在WinForm开发中必不可 ...
- C# 多线程编程第一步——理解多线程
一.进程.线程及多线程的概念 什么是多线程呢?不理解. 那什么是线程呢?说到线程就不得不说说进程.我在网上搜索也搜索了一些资料,大部分所说的进程其实是很抽象的东西.通俗的来讲,进程就是一个应用程序开始 ...
- 数据结构(逻辑结构,物理结构,特点) C#多线程编程的同步也线程安全 C#多线程编程笔记 String 与 StringBuilder (StringBuffer) 数据结构与算法-初体验(极客专栏)
数据结构(逻辑结构,物理结构,特点) 一.数据的逻辑结构:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关.逻辑结构包括: 集合 数 ...
随机推荐
- Android的一个自定义的动态添加Dialog类
android里面会有自己内置的Dialog的提示框,也算是比较方便的了,但是为了省点时间,我们在项目里面添加了一个自己的Dialog类,这个类实现了能够动态的添加按钮和一些提示语句或者其他的显示效果 ...
- 数据结构(左偏树):HDU 1512 Monkey King
Monkey King Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- 部署ASP.Net项目 遇到总是启用目录浏览或者报HTTP 错误 403.14 - Forbidden 的原因
部署Asp.Net 网站总是报下面的问题 原因: 没有为网站指定默认文档,增加默认文档 1.选中“默认文档” 2.点击右边“打开功能” 点击右边“添加”按钮,把你想作为的默认页面添加就可以了,重启服务 ...
- Threading Module源码概述(三)
Threading中的Thread threading中一个关键的组件是threading.Thread. class Thread(_Verbose): __initialized = False ...
- RHEL 6.4 安装svn和apache
1.安装软件包(RHEL已经按默认设置安装完成) 需要安装的.rpm软件包: postgresql-libs perl-URI subversion mod_dav_svn 2.创建svn文件夹和版本 ...
- 从一个简单的Java单例示例谈谈并发 JMM JUC
原文: http://www.open-open.com/lib/view/open1462871898428.html 一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这 ...
- 使用Xcode8的Instruments检测解决iOS内存泄露(leak)
在苹果没有出ARC(自动内存管理机制)时,我们几乎有一半的开发时间都耗费在这么管理内存上.后来苹果很人性的出了ARC,虽然在很大程度上,帮助我们开发者节省了精力和时间.但是我们在开发过程中,由于种种原 ...
- HighCharts 具体使用及API文档说明
一.HighCharts开发说明: HighCharts开发实际上配置HighCharts每一个部分,比方配置标题(title),副标题(subtitle)等,当中每一个部分又有更细的參数配置,比方标 ...
- Java 实现字符串反转
方法一: public class StringReverse { public void swap(char[] arr, int begin, int end) { while(begin < ...
- rsync是类unix系统下的数据镜像备份工具
http://baike.baidu.com/view/1183189.htm Ubuntu安装: sudo apt-get install rsync RedHat: yum install r ...