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) 数据结构与算法-初体验(极客专栏)
数据结构(逻辑结构,物理结构,特点) 一.数据的逻辑结构:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关.逻辑结构包括: 集合 数 ...
随机推荐
- 数学(矩阵乘法,随机化算法):POJ 3318 Matrix Multiplication
Matrix Multiplication Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17783 Accepted: ...
- [Locked] Verify Preorder Sequence in Binary Search Tree
Verify Preorder Sequence in Binary Search Tree Given an array of numbers, verify whether it is the c ...
- Censored! - POJ 1625(ac自动机+简单dp+高精度运算)
题目大意:首先给一个字符集合,这个集合有N个字符,然后需要一个长度为M的句子,但是据子里面不能包含的串有P个,每个串里面的字符都是有字符集和里面的字符构成的,现在想知道最多能构造多少个不重复的句子. ...
- 将对象格式的style转换为字符串格式
var style = { position:'absolute', background:'red', width:'2px', height:'2px', color:'#fff', top:x, ...
- redmine安装插件流程
1.redmine用一键安装即可2.进入C:\Bitnami\redmine-3.1.1-1\,执行use_redmine.exe,进入dos系统 不能用cmd进入.3.把文件拷贝到C:\Bitnam ...
- VMware vSphere 服务器虚拟化之二十五 桌面虚拟化之终端服务池
VMware vSphere 服务器虚拟化之二十五 桌面虚拟化之终端服务池 终端服务池是指由一台或多台微软终端服务器提供服务的桌面源组成的池.终端服务器桌面源可交付多个桌面.它具有以下特征: 1.终端 ...
- Nginx优化具体,应对高并发
nginx指令中的优化(配置文件) worker_processes 8; nginx进程数,建议依照cpu数目来指定.一般为它的倍数. worker_cpu_affinity 00000001 ...
- android:Adb connection Error:远程主机强迫关闭了一个现有的连接
用真机调试程序的时候,eclipse的console总是出现如下的错误“Adb connection Error:远程主机强迫关闭了一个现有的连接” 问题出现的原因:这是ddms调用adb引发的. 经 ...
- rsyslog安装
http://www.rsyslog.com/downloads/download-other/ http://www.rsyslog.com/download/stable-download/pag ...
- mac svn .a文件的上传方法
1.首先确认是否安装了Command Line Tools,如果没有,就Xcode-Preference-Downloads,选择Command Line Tools-install就可以了 2.打开 ...