C# 多线程编程 ThreadStart ParameterizedThreadStart

原文地址:http://club.topsage.com/thread-657023-1-1.html     

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

View Code
 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类型参数时,必须在   启动方法中进行相应的类型转换。
    下面就是一个例子,在启动线程时指定了线程的暂停间隔,代码如下:

View Code
 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类型,这个可以通过拆箱或者其它办法解决。
     假如我们要启动两个线程,每个线程的暂停间隔不一样,启动代码如下:

  

View Code
 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 Code
 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实例放在引入的类中,这种情况适合于在线程中处理的业务逻辑比较复杂的情况。在前不久处理的一个项目中我用过这种情况,它是用来实现双向数据传输的。
     如果实现上面的效果,代码如下:

  

View Code
 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类库中虽然存在着庞大的类库,但是并不是总会有合适的类来解决我们所遇到的问题,但是只要肯动脑筋总会想到合适的办法。

转载于:https://www.cnblogs.com/xiaoyaozhe/archive/2011/11/10/2244110.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/475418.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hive的查找语法

基本语法格式&#xff1a; select [all | DISTINCT ] a.id, a.sname, a.age from student a join student02 b on a.id b.id # 匹配函数 where a.age >18 # 条件语句 group by a.age having a.age >18 # 分组,having:分组后的筛选条件 order by a.age # 全局排序 sort …

动词ing基本用法_动词ing的用法

动词ing的用法2020-09-14 11:41:52文/董月表示现在(指说话人说话时)正在发生的事情&#xff1b;习惯进行&#xff1a;表示长期的或重复性的动作&#xff0c;说话时动作未必正在进行&#xff1b;表示渐变的动词有&#xff1a;get&#xff0c;grow&#xff0c;become&#xff0c;…

LeetCode 1498. 满足条件的子序列数目(排序+二分查找+快速幂)

1. 题目 给你一个整数数组 nums 和一个整数 target 。 请你统计并返回 nums 中能满足其最小元素与最大元素的 和 小于或等于 target 的 非空 子序列的数目。 由于答案可能很大&#xff0c;请将结果对 10^9 7 取余后返回。 示例 1&#xff1a; 输入&#xff1a;nums [3,5,…

Matlab编程学习笔记【待续】

最近想用Matlab进行数据分析&#xff0c;算法性能测试&#xff0c;平时由于用的是C、C&#xff0c;因此很多习惯都一时改不了&#xff0c;这里自己列出来一些Matlab中明显不同的地方。 矩阵单元元素访问方式&#xff1a;A(1,2)---A[1][2]选取矩阵某个行或者列&#xff1a;A(:,1…

Hive的视图

创建视图 create view my_view as select * from student; 注意&#xff1a; hive中的视图仅仅是存储了SQL语句的快捷方式&#xff0c;在查询的时候才执行&#xff1b;hive中的视图只有逻辑视图&#xff0c;没有物化视图&#xff1b;hive中的视图只支持查询&#xff0c;不支…

animation 先执行一次 在持续执行_这一次,彻底弄懂 JavaScript 执行机制

本文来源&#xff1a;ssssyokihttps://juejin.im/post/6844903512845860872不论你是javascript新手还是老鸟&#xff0c;不论是面试求职&#xff0c;还是日常开发工作&#xff0c;我们经常会遇到这样的情况&#xff1a;给定的几行代码&#xff0c;我们需要知道其输出内容和顺序…

[scikit-learn 机器学习] 5. 多元线性回归

文章目录1. 多元线性回归2. 多项式回归3. 正则化4. 线性回归应用举例&#xff08;酒质量预测&#xff09;4.1 数据预览4.2 模型验证5. 梯度下降法本文为 scikit-learn机器学习&#xff08;第2版&#xff09;学习笔记1. 多元线性回归 模型 yαβ1x1β2x2...βnxny \alpha\bet…

mac笔记本修改 mysql 的密码

第一种 mysql版本&#xff1a;5.7.17 1.首先我们要关闭mysql服务 sudo /usr/local/mysql/support-files/mysql.server stop 2.我们要用安全模式启动mysql sudo /usr/local/mysql/bin/mysqld_safe --skip-grant-tables 3.使用root账号登录mysql服务 /usr/local/mysql/bin/mysql …

LeetCode 831. 隐藏个人信息

1. 题目 给你一条个人信息字符串 S&#xff0c;它可能是一个 邮箱地址 &#xff0c;也可能是一串 电话号码 。 我们将隐藏它的隐私信息&#xff0c;通过如下规则: 电子邮箱 定义名称 name 是长度大于等于 2 &#xff08;length ≥ 2&#xff09;&#xff0c;并且只包含小写…

oa项目经验描述_简历中项目经验模版

项目名称&#xff1a;OA(办公自动化)开发工具&#xff1a;MyEclipse 8.6 , Oracle 11g , Tomcat 6.0.18项目描述(1, SSH框架版)&#xff1a;OA主要功能模块分为首页Portlet展示、协同审批、协同工作、日历、资源管理、知识中心、新闻中心、通讯录、系统管理。是一套很好的办公自…

分离

web2.0到处都是分离与聚合的思想&#xff1a; jquery实现了表现层的行为与内容的分离 zendframework为首的mvc架构实现了逻辑架构的控制、模块、表现层的分离 mysql为例的master-slave架构实现了服务与备份的分离 hadoop为首的虚拟化架构实现了单点计算与群体计算的结合 css实现…

hive-内置函数(常用内置函数汇总)

show functions; #查看所有内置函数&#xff0c;共271个 show function sum; #查看sum函数的描述信息 show function extended sum; #查看内置函数的描述信息和举例的使用方法 举例数据表&#xff1a;stu id name address score credit 01 huang hebi,changzhou,dalian …

LeetCode 828. 统计子串中的唯一字符(中心扩展)

1. 题目 我们定义了一个函数 countUniqueChars(s) 来统计字符串 s 中的唯一字符&#xff0c;并返回唯一字符的个数。 例如&#xff1a;s “LEETCODE” &#xff0c;则其中 “L”, “T”,“C”,“O”,“D” 都是唯一字符&#xff0c;因为它们只出现一次&#xff0c;所以 coun…

钢笔的保养

钢笔其实很泼辣的不需要用心的保养&#xff0c;但如果太不注意了&#xff0c;也会早早损毁了一支好笔。所以&#xff0c;为了自己方便地更长久些&#xff0c;还是要保养一下。保养的方法很简单&#xff0c;就是&#xff1a; 用前先浸&#xff0c;墨水不混&#xff0c;定期清洗。…

hive - 自定义函数(超详细步骤,手把手的交)

用Java开发自定义函数&#xff0c;步骤&#xff1a; 1.eclipse上新建一个工程project&#xff08;db2019)&#xff1b; 2.导jar依赖包&#xff1a; db2019右键 --build path --configure... --add library --user library --new(新建一个library(hive2.3.2_jar)) --add ext…

LeetCode 1053. 交换一次的先前排列

1. 题目 给你一个正整数的数组 A&#xff08;其中的元素不一定完全不同&#xff09;&#xff0c;请你返回可在 一次交换&#xff08;交换两数字 A[i] 和 A[j] 的位置&#xff09;后得到的、按字典序排列小于 A 的 最大可能排列。 如果无法这么操作&#xff0c;就请返回原数组…

bootstrap 树形表格渲染慢_layUI之树状表格异步加载组件treetableAsync.js(基于treetable.js)...

概述后台框架中使用树状表格是非常常用的操作&#xff0c;layUI本身并没有这种组件。 第三方的treetable.js做到了完美的实现&#xff0c;但是不能实现在双击时异步加载数据&#xff0c;本文就是站在了巨人的肩膀上实现的异步加载的树状表格~1. 使用说明本组件基于treetable.js…

EchoServer

using System;using System.Net.Sockets;using System.IO;using System.Net; namespace ConsoleApplication1{ class EchoServer { public static void Main11() { // TcpListener监听端口1234 IPAddress ipAd IPAddress.Parse(&qu…

hive - 解析 json

内置函数&#xff1a;get_json_object(json串,解析路径) 解析路径说明&#xff1a; $ :跟对象 . :子对象 [] :数组下标 * :所有 举例&#xff1a; 数据样例&#xff1a; {"movie":"1190","rate":"4.8","timestamp":…

[scikit-learn 机器学习] 6. 逻辑回归

文章目录1. 逻辑回归二分类2. 垃圾邮件过滤2.1 性能指标2.2 准确率2.3 精准率、召回率2.4 F1值2.5 ROC、AUC3. 网格搜索调参4. 多类别分类5. 多标签分类5.1 多标签分类性能指标本文为 scikit-learn机器学习&#xff08;第2版&#xff09;学习笔记逻辑回归常用于分类任务 1. 逻…