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,一经查实,立即删除!

相关文章

Matlab编程学习笔记【待续】

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

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…

LeetCode 831. 隐藏个人信息

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

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

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

[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. 逻…

libsvm回归参数寻优cgp_【lightgbm/xgboost/nn代码整理二】xgboost做二分类,多分类以及回归任务...

1.简介该部分是代码整理的第二部分&#xff0c;为了方便一些初学者调试代码&#xff0c;作者已将该部分代码打包成一个工程文件&#xff0c;包含简单的数据处理、xgboost配置、五折交叉训练和模型特征重要性打印四个部分。数据处理部分参考&#xff1a;代码整理一&#xff0c;这…

[scikit-learn 机器学习] 7. 朴素贝叶斯

文章目录1. 朴素贝叶斯2. NB 与 逻辑回归对比本文为 scikit-learn机器学习&#xff08;第2版&#xff09;学习笔记相关知识参考&#xff1a;《统计学习方法》朴素贝叶斯法&#xff08;Naive Bayes&#xff0c;NB&#xff09; 1. 朴素贝叶斯 通过最大概率来预测类&#xff1a…

塔菲克蓝牙适配器驱动_小身材,大功能,biaze毕亚兹USB蓝牙适配器开箱体验

在日常生活中&#xff0c;我们平时使用的台式电脑或是笔记本电脑&#xff0c;想要传输数据或者音频的时候&#xff0c;都是需要借助数据传输线或是U盘等传输设备&#xff0c;使用过程可想而知&#xff0c;有点麻烦。我们都知道&#xff0c;手机是有蓝牙传输功能的&#xff0c;只…

HDU1003——MAX SUM

简单DP&#xff0c;状态转移公式&#xff1a;num[j].data max{num[j].data, num[j].datanum[j-1].data}&#xff0c;也就是保证加上前一个数不失自己的值减小。 View Code #include <stdio.h>#define N 100010#define inf 9999999struct _num{int data;int pre;int nex…

[scikit-learn 机器学习] 8. 非线性分类和决策树

文章目录1. 特征选择标准2. 网页广告预测2.1 数量处理2.2 网格搜索模型参数3. 决策树优缺点本文为 scikit-learn机器学习&#xff08;第2版&#xff09;学习笔记相关知识&#xff1a;《统计学习方法》决策树&#xff08;Decision Tree&#xff0c;DT&#xff09; 1. 特征选择…

智慧新泰时空大数据与云平台_智慧警务大数据云平台开发情报研判系统解决方案...

智慧公安作为公安信息化开展到高级阶段的一种警务形态&#xff0c;“智慧公安”主要采用物联网、云计算、无线通讯、智能动态感知分析等新一代信息技术,将公安工作IT根底设备与物理设备、人际环境等高度交融,以提供智能化公安决策与效劳。智慧警务大数据云平台开发情报研判系统…

RGB颜色查询对照表#FFFFFF

大致是下图这样的&#xff0c;有需要的可以点击下面的连接复制使用&#xff1a; https://www.114la.com/other/rgb.htm

ikbc机械键盘打字出现重复_超小无线机械键盘,绝佳移动打字体验

NuType筹资信息产品名称NuType上线平台Kickstarter发起团队NUPHY发起地区中国香港目标金额80,000HKD筹集金额1,301,212HKD完全进度1,627%支持人数1,612最低价格697HKD上线时间2019/11/13-2019/12/28创次方/制表时间&#xff1a;2019年12月28日文/大智笔电键盘的打字体验远不及桌…

MySQL - 定时任务(每天凌晨1点、每小时、每分钟、某一时间点)

常用的一定要写在前面 # 从2019-10-11开始&#xff0c;每天的00:30:00执行定时任务 ON SCHEDULE EVERY 1 DAY STARTS 2019-10-11 00:30:00 # 每天的凌晨1点执行定时任务 ON SCHEDULE EVERY 1 DAY STARTS DATE_ADD(DATE_ADD(CURDATE(), INTERVAL 1 DAY), INTERVAL 1 HOUR)# 特…

极光无限渗透测试面经_认识工业以太网及线缆测试

工业以太网由于其固有的可靠性、高性能和互操作性&#xff0c;已经渗透到工厂车间&#xff0c;成为自动化和控制系统的首选通信协议。近年&#xff0c;工业以太网的市场份额已经超过了传统的现场总线协议&#xff0c;总线协议通常需要多个独立和专有的布线设施。为了满足工业环…

LeetCode 286. 墙与门(BFS)

文章目录1. 题目2. 解题2.1 BFS 超时解2.2 从门开始逆向BFS1. 题目 你被给定一个 m n 的二维网格&#xff0c;网格中有以下三种可能的初始化值&#xff1a; -1 表示墙或是障碍物0 表示一扇门INF 无限表示一个空的房间。然后&#xff0c;我们用 231 - 1 2147483647 代表 INF…

法斗几个月长鼻筋_路医生说丨脚底板早起一下地特别疼?得了足底筋膜炎,该怎么办?...

老李很奇怪&#xff0c;他压根就没有受过伤&#xff0c;怎么突然就脚底板疼了起来。就是这两天走的稍多了点&#xff0c;也不知道为什么脚底板就开始疼了&#xff0c;走路踩地就疼&#xff0c;尤其是早晨起床脚一踩地&#xff0c;那酸爽简直了&#xff0c;刚下地的前几步走起来…

Power BI连接MySQL 提示错误......未能加载文件或程序集......或它的某一个依赖项

Power BI连接MySQL数据库时报错&#xff1a; 提示错误未能加载文件或程序集“MySql.Data, Version5.1.4.0, Cultureneutral,........”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 解决办法&#xff1a;下载MySQL.Data.dll(5.1.4)程序集&#xff01; 解压…

LeetCode 346. 数据流中的移动平均值(队列)

文章目录1. 题目2. 解题1. 题目 给定一个整数数据流和一个窗口大小&#xff0c;根据该滑动窗口的大小&#xff0c;计算其所有整数的移动平均值。 示例: MovingAverage m new MovingAverage(3); m.next(1) 1 m.next(10) (1 10) / 2 m.next(3) (1 10 3) / 3 m.next(5) …