博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 以ThreadStart方式实现多线程
阅读量:5052 次
发布时间:2019-06-12

本文共 6984 字,大约阅读时间需要 23 分钟。

 

3.1 使用ThreadStart委托

这 里先以一个例子体现一下多线程带来的好处,首先在Message类中建立一个方法ShowMessage(),里面显示了当前运行线程的Id,并使用 Thread.Sleep(int ) 方法模拟部分工作。在main()中通过ThreadStart委托绑定Message对象的ShowMessage()方法,然后通过 Thread.Start()执行异步方法。

1       public class Message 2       { 3           public void ShowMessage() 4           { 5               string message = string.Format("Async threadId is :{0}", 6                                               Thread.CurrentThread.ManagedThreadId); 7               Console.WriteLine(message); 8    9               for (int n = 0; n < 10; n++)10               {11                   Thread.Sleep(300);   12                   Console.WriteLine("The number is:" + n.ToString()); 13               }14           }15       }16   17       class Program18       {19           static void Main(string[] args)20           {21               Console.WriteLine("Main threadId is:"+22                                 Thread.CurrentThread.ManagedThreadId);23               Message message=new Message();24               Thread thread = new Thread(new ThreadStart(message.ShowMessage));25               thread.Start();26               Console.WriteLine("Do something ..........!");27               Console.WriteLine("Main thread working is complete!");28               29           }30       }
请注意运行结果,在调用Thread.Start()方法后,系统以异步方式运行Message.ShowMessage(),而主线程的操作是继续执行的,在Message.ShowMessage()完成前,主线程已完成所有的操作。

 

3.2 使用ParameterizedThreadStart委托

ParameterizedThreadStart 委托与ThreadStart委托非常相似,但ParameterizedThreadStart委托是面向带参数方法的。注意 ParameterizedThreadStart 对应方法的参数为object,此参数可以为一个值对象,也可以为一个自定义对象。

1     public class Person 2     { 3         public string Name 4         { 5             get; 6             set; 7         } 8         public int Age 9         {10             get;11             set;12         }13     }14 15     public class Message16     {17         public void ShowMessage(object person)18         {19             if (person != null)20             {21                 Person _person = (Person)person;22                 string message = string.Format("\n{0}'s age is {1}!\nAsync threadId is:{2}",23                     _person.Name,_person.Age,Thread.CurrentThread.ManagedThreadId);24                 Console.WriteLine(message);25             }26             for (int n = 0; n < 10; n++)27             {28                 Thread.Sleep(300);   29                 Console.WriteLine("The number is:" + n.ToString()); 30             }31         }32     }33 34     class Program35     {36         static void Main(string[] args)37         {     38             Console.WriteLine("Main threadId is:"+Thread.CurrentThread.ManagedThreadId);39             40             Message message=new Message();41             //绑定带参数的异步方法 42             Thread thread = new Thread(new ParameterizedThreadStart(message.ShowMessage));43             Person person = new Person();44             person.Name = "Jack";45             person.Age = 21;46             thread.Start(person);  //启动异步线程 47             48             Console.WriteLine("Do something ..........!");49             Console.WriteLine("Main thread working is complete!");50              51         }52     }
运行结果:

 

3.3 前台线程与后台线程

注意以上两个例子都没有使用Console.ReadKey(),但系统依然会等待异步线程完成后才会结束。这是因为使用Thread.Start()启动的线程默认为前台线程,而系统必须等待所有前台线程运行结束后,应用程序域才会自动卸载。

在第二节曾经介绍过线程Thread有一个属性IsBackground,通过把此属性设置为true,就可以把线程设置为后台线程!这时应用程序域将在主线程完成时就被卸载,而不会等待异步线程的运行。

 

3.4 挂起线程

为了等待其他后台线程完成后再结束主线程,就可以使用Thread.Sleep()方法。

1     public class Message 2     { 3         public void ShowMessage() 4         { 5             string message = string.Format("\nAsync threadId is:{0}", 6                                            Thread.CurrentThread.ManagedThreadId); 7             Console.WriteLine(message); 8             for (int n = 0; n < 10; n++) 9             {10                 Thread.Sleep(300);11                 Console.WriteLine("The number is:" + n.ToString());12             }13         }14     }15 16     class Program17     {18         static void Main(string[] args)19         {     20             Console.WriteLine("Main threadId is:"+21                               Thread.CurrentThread.ManagedThreadId);22             23             Message message=new Message();24             Thread thread = new Thread(new ThreadStart(message.ShowMessage));25             thread.IsBackground = true;26             thread.Start();27             28             Console.WriteLine("Do something ..........!");29             Console.WriteLine("Main thread working is complete!");30             Console.WriteLine("Main thread sleep!");31             Thread.Sleep(5000);32         }33     }

运行结果如下,此时应用程序域将在主线程运行5秒后自动结束

但 系统无法预知异步线程需要运行的时间,所以用通过Thread.Sleep(int)阻塞主线程并不是一个好的解决方法。有见及此,.NET专门为等待异 步线程完成开发了另一个方法thread.Join()。把上面例子中的最后一行Thread.Sleep(5000)修改为 thread.Join() 就能保证主线程在异步线程thread运行结束后才会终止。

 

3.5 Suspend 与 Resume (慎用)

Thread.Suspend() 与 Thread.Resume()是在Framework1.0 就已经存在的老方法了,它们分别可以挂起、恢复线程。但在Framework2.0中就已经明确排斥这两个方法。这是因为一旦某个线程占用了已有的资源, 再使用Suspend()使线程长期处于挂起状态,当在其他线程调用这些资源的时候就会引起死锁!所以在没有必要的情况下应该避免使用这两个方法。

 

3.6 终止线程

若想终止正在运行的线程,可以使用Abort()方法。在使用Abort()的时候,将引发一个特殊异常 ThreadAbortException 。

若想在线程终止前恢复线程的执行,可以在捕获异常后 ,在catch(ThreadAbortException ex){...} 中调用Thread.ResetAbort()取消终止。
而使用Thread.Join()可以保证应用程序域等待异步线程结束后才终止运行。

1          static void Main(string[] args) 2          { 3              Console.WriteLine("Main threadId is:" + 4                                Thread.CurrentThread.ManagedThreadId); 5   6              Thread thread = new Thread(new ThreadStart(AsyncThread)); 7              thread.IsBackground = true; 8              thread.Start(); 9              thread.Join();10  11          }     12          13          //以异步方式调用 14          static void AsyncThread()15          {16              try17              {18                  string message = string.Format("\nAsync threadId is:{0}",19                     Thread.CurrentThread.ManagedThreadId);20                  Console.WriteLine(message);21  22                  for (int n = 0; n < 10; n++)23                  {24                      //当n等于4时,终止线程 25                      if (n >= 4)26                      {27                          Thread.CurrentThread.Abort(n);28                      }29                      Thread.Sleep(300);30                      Console.WriteLine("The number is:" + n.ToString());31                  }32              }33              catch (ThreadAbortException ex)34              {35                  //输出终止线程时n的值 36                  if (ex.ExceptionState != null)37                      Console.WriteLine(string.Format("Thread abort when the number is: {0}!", 38                                                       ex.ExceptionState.ToString()));39                 40                  //取消终止,继续执行线程 41                  Thread.ResetAbort();42                  Console.WriteLine("Thread ResetAbort!");43              }44  45              //线程结束 46              Console.WriteLine("Thread Close!");47          }

运行结果如下

转载于:https://www.cnblogs.com/lvdongjie/p/5001062.html

你可能感兴趣的文章
list-style-type -- 定义列表样式
查看>>
Ubuntu 编译出现 ISO C++ 2011 不支持的解决办法
查看>>
Linux 常用命令——cat, tac, nl, more, less, head, tail, od
查看>>
VueJS ElementUI el-table 的 formatter 和 scope template 不能同时存在
查看>>
Halcon一日一练:图像拼接技术
查看>>
iOS设计模式 - 中介者
查看>>
centos jdk 下载
查看>>
HDU 1028 Ignatius and the Princess III(母函数)
查看>>
(转)面向对象最核心的机制——动态绑定(多态)
查看>>
token简单的使用流程。
查看>>
django创建项目流程
查看>>
Vue 框架-01- 入门篇 图文教程
查看>>
多变量微积分笔记24——空间线积分
查看>>
poi操作oracle数据库导出excel文件
查看>>
(转)Intent的基本使用方法总结
查看>>
Windows Phone开发(24):启动器与选择器之发送短信
查看>>
JS截取字符串常用方法
查看>>
Google非官方的Text To Speech和Speech Recognition的API
查看>>
stdext - A C++ STL Extensions Libary
查看>>
Django 内建 中间件组件
查看>>