1. 原文地址:http://club.topsage.com/thread-657023-1-1.html
  2. 在实例化Thread的实例,需要提供一个委托,在实例化这个委托时所用到的参数是线程将来启动时要运行的方法。在.net中提供了两种启动线程的方式,一种是不带参数的启动方式,另一种是带参数的启动的方式。
  3. 不带参数的启动方式
  4. 如果启动参数时无需其它额外的信息,可以使用ThreadStart来实例化Thread,如下面的代码:
  5. 1 using System;
  6. 2 using System.Collections.Generic;
  7. 3 using System.Text;
  8. 4 using System.Threading;
  9. 5
  10. 6 namespace StartThread
  11. 7 {
  12. 8          class Program
  13. 9          {
  14. 10                  int interval = 200;
  15. 11                  static void Main(string[] args)
  16. 12                  {
  17. 13                          Program p = new Program();
  18. 14                          Thread nonParameterThread = new Thread(new ThreadStart(p.NonParameterRun));
  19. 15                          nonParameterThread.Start();
  20. 16                  }
  21. 17                  ///<summary>
  22. 18 /// 不带参数的启动方法
  23. 19 ///</summary>
  24. 20                  public void NonParameterRun()
  25. 21                  {
  26. 22                          for (int i = 0; i < 10; i++)
  27. 23                          {
  28. 24                                  Console.WriteLine("系统当前时间毫秒值:"+DateTime.Now.Millisecond.ToString());
  29. 25                                  Thread.Sleep(interval);//让线程暂停
  30. 26                          }
  31. 27          }
  32. 28 }
  33. 程序的运行效果我们不用运行也会知道,那就是在循环中将系统当前时间的毫秒部分输出出来,在每次输出之后会将当前线程暂停一下,直到10次之后运行完毕,终止线程的执行。
  34. 在上面的代码中我们是通过定义全局变量的方法来指定线程暂停间隔,按照这种方法,假如要运行10个线程,每个线程的暂停间隔不一样的话,就需要定义10个全局变量,虽然最终不影响系统的运行效果,但是总觉得不是太爽。
  35. 有没有比较简单一点的办法呢?有!那就是使用带参数的启动方法。
  36. 带参数的启动方法
  37. 如果要在实例化线程时要带一些参数,就不能用ThreadStart委托作为构造函数的参数来实例化Thread了,而要 ParameterizedThreadStart委托,和ThreadStart一样的是它也是线程启动时要执行的方法,和ThreadStart不同的是,它在实例化时可以用一个带有一个Object参数的方法作为构造函数的参数,而实例化ThreadStart时所用到的方法是没有参数的。
  38. 为什么是Object这样的参数呢?很简单,因为在.net中Object是所有类型的基类,用它可以表示Array(数组)、Interface(接口)、ValueType(值类型,如bool,byte,char,short,int,float,long,double等)、class(类)等.net中的类型。当然,这也意味着如果你要启动一个线程,给它传递一个int类型参数时,必须在   启动方法中进行相应的类型转换。
  39. 下面就是一个例子,在启动线程时指定了线程的暂停间隔,代码如下:
  40. 1 using System;
  41. 2 using System.Collections.Generic;
  42. 3 using System.Text;
  43. 4 using System.Threading;
  44. 5
  45. 6 namespace StartThread
  46. 7 {
  47. 8          class Program
  48. 9          {
  49. 10                  int interval = 200;
  50. 11                  static void Main(string[] args)
  51. 12                  {
  52. 13                          Program p = new Program();
  53. 14
  54. 15                          Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));
  55. 16                          parameterThread.Name = "Thread A:";
  56. 17                          parameterThread.Start(30);
  57. 18                  }
  58. 19
  59. 20                  ///<summary>
  60. 21 /// 带参数的启动方法
  61. 22 ///</summary>
  62. 23 ///<param name="ms">让线程在运行过程中的休眠间隔</param>
  63. 24                  public void ParameterRun(object ms)
  64. 25                  {
  65. 26                          int j = 10;
  66. 27                          int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常
  67. 28                          for (int i = 0; i < 10; i++)
  68. 29                          {
  69. 30                                  Console.WriteLine(Thread.CurrentThread.Name+"系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());
  70. 31                                  Thread.Sleep(j);//让线程暂停
  71. 32                          }
  72. 33                  }
  73. 34          }
  74. 35 }
  75. 在这个方法里,我们在启动线程时顺便指定了线程的暂停间隔,也就是这句:
  76. parameterThread.Start(30);
  77. 线程启动时运行的方法是public void ParameterRun(object ms),这个值为30的int类型变量被装箱成object,所以在方法中还需要将它转换成int类型,这个可以通过拆箱或者其它办法解决。
  78. 假如我们要启动两个线程,每个线程的暂停间隔不一样,启动代码如下:
  79.   
  80. 1 using System;
  81. 2 using System.Collections.Generic;
  82. 3 using System.Text;
  83. 4 using System.Threading;
  84. 5
  85. 6 namespace StartThread
  86. 7 {
  87. 8          class Program
  88. 9          {
  89. 10                  int interval = 200;
  90. 11                  static void Main(string[] args)
  91. 12                  {
  92. 13                          Program p = new Program();
  93. 14
  94. 15                          Thread parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));
  95. 16                          parameterThread.Name = "Thread A:";
  96. 17                          parameterThread.Start(30);
  97. 18                          //启动第二个线程
  98. 19                          parameterThread = new Thread(new ParameterizedThreadStart(p.ParameterRun));
  99. 20                          parameterThread.Name = "Thread B:";
  100. 21                          parameterThread.Start(60);
  101. 22                  }
  102. 23
  103. 24                  ///<summary>
  104. 25 /// 带参数的启动方法
  105. 26 ///</summary>
  106. 27 ///<param name="ms">让线程在运行过程中的休眠间隔</param>
  107. 28                  public void ParameterRun(object ms)
  108. 29                  {
  109. 30                          int j = 10;
  110. 31                          int.TryParse(ms.ToString(), out j);//这里采用了TryParse方法,避免不能转换时出现异常
  111. 32                          for (int i = 0; i < 10; i++)
  112. 33                          {
  113. 34                                  Console.WriteLine(Thread.CurrentThread.Name+"系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());
  114. 35                                  Thread.Sleep(j);//让线程暂停
  115. 36                          }
  116. 37                  }
  117. 38          }
  118. 39 }
  119. 对上面的代码做一点说明,就是线程启动之后,线程的实例不必再存在,例如在上面的代码中我用的是同一个实例实例化了两个线程,并且这两个线程运行很正常。
  120. 继续探索
  121. 上面解决了一个问题,如果在启动线程时需要参数如何解决,如果针对上面的问题继续发掘,比如:在启动线程时不但要指定线程的暂停间隔,还需要指定循环次数(在上面的所有例子中都是执行10次的),这个问题该如何解决呢?
  122. 有两种办法可以解决:
  123. 首先可以继续在ParameterizedThreadStart这里做文章,因为这里可以使用一个Object类型的参数,那么可以通过数组或者一个类来解决(因为它们都是Object的子类)。我在做某个系统时确实采用数组处理过这种情况,这样就要求在线程启动方法中必须清楚知道数组中每个参数的用途,不是太方便。
  124. 这里说说重新定义一个实体类来解决的方法,代码如下。
  125. 1 using System;
  126. 2 using System.Collections.Generic;
  127. 3 using System.Text;
  128. 4 using System.Threading;
  129. 5
  130. 6 namespace StartThread
  131. 7 {
  132. 8          class MyThreadParameter
  133. 9          {
  134. 10                  private int interval;
  135. 11                  private int loopCount;
  136. 12                  ///<summary>
  137. 13 /// 循环次数
  138. 14 ///</summary>
  139. 15                  public int LoopCount
  140. 16                  {
  141. 17                          get { return loopCount; }
  142. 18                  }
  143. 19
  144. 20                  ///<summary>
  145. 21 /// 线程的暂停间隔
  146. 22 ///</summary>
  147. 23                  public int Interval
  148. 24                  {
  149. 25                          get { return interval; }
  150. 26                  }
  151. 27             ///<summary>
  152. 28 /// 构造函数
  153. 29 ///</summary>
  154. 30 ///<param name="interval">线程的暂停间隔</param>
  155. 31 ///<param name="loopCount">循环次数</param>
  156. 32                  public MyThreadParameter(int interval,int loopCount)
  157. 33                  {
  158. 34                          this.interval = interval;
  159. 35                          this.loopCount = loopCount;
  160. 36                  }
  161. 37          }
  162. 38          class Program
  163. 39          {
  164. 40                  int interval = 200;
  165. 41                  static void Main(string[] args)
  166. 42                  {
  167. 43                          Program p = new Program();
  168. 44
  169. 45                          Thread parameterThread = new Thread(new ParameterizedThreadStart(p.MyParameterRun));
  170. 46                          parameterThread.Name = "Thread A:";
  171. 47                          MyThreadParameter paramter = new MyThreadParameter(50, 20);
  172. 48                          parameterThread.Start(paramter);
  173. 49                  }
  174. 50
  175. 51
  176. 52                  ///<summary>
  177. 53 /// 带多个参数的启动方法
  178. 54 ///</summary>
  179. 55 ///<param name="ms">方法参数</param>
  180. 56                  public void MyParameterRun(object ms)
  181. 57                  {
  182. 58                          MyThreadParameter parameter = ms as MyThreadParameter;//类型转换
  183. 59                          if (parameter != null)
  184. 60                          {
  185. 61                                  for (int i = 0; i < parameter.LoopCount; i++)
  186. 62                                  {
  187. 63                                          Console.WriteLine(Thread.CurrentThread.Name + "系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());
  188. 64                                          Thread.Sleep(parameter.Interval);//让线程暂停
  189. 65                                  }
  190. 66                          }
  191. 67                  }
  192. 68          }
  193. 69 }
  194. 第二种方法和上面方法有些相似,也是需要引入外部类,并且将Thread实例放在引入的类中,这种情况适合于在线程中处理的业务逻辑比较复杂的情况。在前不久处理的一个项目中我用过这种情况,它是用来实现双向数据传输的。
  195. 如果实现上面的效果,代码如下:
  196.   
  197. 1 using System;
  198. 2 using System.Collections.Generic;
  199. 3 using System.Text;
  200. 4 using System.Threading;
  201. 5
  202. 6 namespace StartThread
  203. 7 {
  204. 8          class MyThreadParameter
  205. 9          {
  206. 10                  private int interval;
  207. 11                  private int loopCount;
  208. 12                  private Thread thread;
  209. 13
  210. 14     ///<summary>
  211. 15 /// 构造函数
  212. 16 ///</summary>
  213. 17 ///<param name="interval">线程的暂停间隔</param>
  214. 18 ///<param name="loopCount">循环次数</param>
  215. 19                  public MyThreadParameter(int interval,int loopCount)
  216. 20                  {
  217. 21                          this.interval = interval;
  218. 22                          this.loopCount = loopCount;
  219. 23                          thread = new Thread(new ThreadStart(Run));
  220. 24                  }
  221. 25
  222. 26                  public void Start()
  223. 27                  {
  224. 28                          if (thread != null)
  225. 29                          {
  226. 30                                  thread.Start();
  227. 31                          }
  228. 32                  }
  229. 33
  230. 34                  private void Run()
  231. 35                  {
  232. 36                          for (int i = 0; i < loopCount; i++)
  233. 37                          {
  234. 38                                  Console.WriteLine("系统当前时间毫秒值:" + DateTime.Now.Millisecond.ToString());
  235. 39                                  Thread.Sleep(interval);//让线程暂停
  236. 40                          }
  237. 41                  }
  238. 42          }
  239. 43          class Program
  240. 44          {
  241. 45                  static void Main(string[] args)
  242. 46                  {
  243. 47                          MyThreadParameter parameterThread = new MyThreadParameter(30, 50);
  244. 48                          parameterThread.Start();
  245. 49                  }
  246. 50
  247. 51          }
  248. 52 }
  249. 上面的代码的运行效果和前面的代码运行效果类似,只不过是将业务处理代码放在一个单独的类MyThreadParameter中,使得MyThreadParameter看起来也像一个Thread,实际上维护的还是其内部的Thread,在一些大型系统中这样做的好处是便于维护。
  250. 总结:在本篇主要讲述如何启动线程的问题,在启动时可能会遇到无需参数、需要多个参数的情况,在这里讲述了如何解决这些问题的思路。在.net类库中虽然存在着庞大的类库,但是并不是总会有合适的类来解决我们所遇到的问题,但是只要肯动脑筋总会想到合适的办法。

C# 多线程编程 ThreadStart ParameterizedThreadStart的更多相关文章

  1. 多线程之 ThreadStart 和 ParameterizedThreadStart 委托

    先看微软如何给出的方法使用,如下查看,我们发现,如下两个委托,分别对应带参数创建线程 和 不带参数创建线程. 下列 委托 方法不带参数 ThreadStart namespace System.Thr ...

  2. 浅述WinForm多线程编程与Control.Invoke的应用

    VS2008.C#3.0在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在W ...

  3. C#多线程编程总结

    VS2008.C#3.0在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在W ...

  4. C#多线程编程笔记

    在开发中经常有遇到因为程序执行的时间过长,而造成程序假死的情况,这是因为我们的程序是同步执行的,当执行到需要长时间的操作时,程序就会等待当前的操作完成,从而造成程序假死.C#的异步与多线程就是为了解决 ...

  5. C#多线程编程实战(二)

    1.1 简介 为了防止一个应用程序控制CPU而导致其他应用程序和操作系统本身永远被挂起这一可能情况,操作系统不得不使用某种方式将物理计算分割为一些虚拟的进程,并给予每个执行程序一定量的计算能力.此外操 ...

  6. C# 多线程编程,传参,接受返回值

    C# 多线程编程,传参,接受返回值 今天将多线程的知识有回顾了下,总结了几点: 新建一个线程(无参数,无返回值) Thread th = new Thread(new ThreadStart(Prin ...

  7. WinForm多线程编程与Control.Invoke的应用浅谈

    在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在WinForm开发中必不可 ...

  8. C# 多线程编程第一步——理解多线程

    一.进程.线程及多线程的概念 什么是多线程呢?不理解. 那什么是线程呢?说到线程就不得不说说进程.我在网上搜索也搜索了一些资料,大部分所说的进程其实是很抽象的东西.通俗的来讲,进程就是一个应用程序开始 ...

  9. 数据结构(逻辑结构,物理结构,特点) C#多线程编程的同步也线程安全 C#多线程编程笔记 String 与 StringBuilder (StringBuffer) 数据结构与算法-初体验(极客专栏)

    数据结构(逻辑结构,物理结构,特点) 一.数据的逻辑结构:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关.逻辑结构包括: 集合 数 ...

随机推荐

  1. SendMessage和PostMessage区别以及WPARAM 和 LPARAM区别

    WPARAM 和 LPARAM wParam和lParam 这两个是Win16系统遗留下来的产物,在Win16API中WndProc有两个参数:一个是WORD类型的16位整型变量:另一个是LONG类型 ...

  2. [Locked] Graph Valid Tree

    Graph Valid Tree Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is ...

  3. Selenium webdriver 操作chrome 浏览器

    Step1: 下载chromedriver. 下载路径: http://chromedriver.storage.googleapis.com/index.html 选择一个合适的下载即可.我下载的是 ...

  4. P - The Shortest Path in Nya Graph-hdu4725(双端队列+拆点)

    题意:有N个点和N层..一层有X个点(0<=X<=N).两邻两层间有一条路花费C.还有M条小路在两个点之间.问从第一个点走到第N个点最短路是多少... 可以考虑在每一层增加一个点,这个点到 ...

  5. Python进程、线程、协程详解

    进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. ...

  6. UVa 108: Maximum Sum

    这道题用暴力解法+动态规划.分析如下: 对于某个1*m的矩阵,即一个数列,求其maximal sub-rectangle,可以通过求最大长连续字串和来求得(这个用到了动态规划). 那么对于n*m的矩阵 ...

  7. [转]【基于zxing的编解码实战】精简Barcode Scanner篇

    通过<[搞定条形码]zxing项目源码解读(2.3.0版本,Android部分)>的分析,现在可以实现最终目标了:精简Barcode Scanner并将其中的编码和解码分离为两个独立的部分 ...

  8. Ruby On Rails 4 hello world,Ruby On Rails上手

    有机会再试一试Rails了,仅仅是原来接触的是2,如今已然变成了4,似乎如今的安装比原来会快些.. Rails 4 安装 针对于安装了RVM gem install rails 没有的话应该主 sud ...

  9. Monitor and diagnose performance in Java SE 6--转载

    Java SE 6 provides an in-depth focus on performance, offering expanded tools for managing and monito ...

  10. TCP异常终止(reset报文)

    在之前做智能家居系统时,师弟做的服务端与WiFI盒子(客户端)进行通信时,总是出现异常情况,然后服务端不停地向客户端发送RESET报文,之前一直都不知道是什么情况,因此一直不知道是什么问题导致的,今天 ...