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 Program
18 {
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 Message
16 {
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 Program
35 {
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 Program
17 {
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 try
17 {
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 }

运行结果如下

C# 以ThreadStart方式实现多线程的更多相关文章

  1. ThreadStart方式实现多线程

    以ThreadStart方式实现多线程 3.1 使用ThreadStart委托 这 里先以一个例子体现一下多线程带来的好处,首先在Message类中建立一个方法ShowMessage(),里面显示了当 ...

  2. java 22 - 22 多线程之 匿名内部类的方式实现多线程

    首先回顾下之前的匿名内部类: 匿名内部类的格式: new 接口或者接口名(){ 重写方法 }; 本质:是该类或者接口的子类对象 匿名内部类方式使用多线程 1.new Thread(){代码-}.sta ...

  3. Java基础 继承的方式创建多线程 / 线程模拟模拟火车站开启三个窗口售票

    继承的方式创建多线程 笔记: /**继承的方式创建多线程 * 线程的创建方法: * 1.创建一个继承于Thread 的子类 * 2.重写Thread类的run()方法 ,方法内实现此子线程 要完成的功 ...

  4. java 多线程:Callable接口;FutureTask类实现对象【Thread、Runnable、Callable三种方式实现多线程的区别】

    Callable接口介绍: Java5开始,Java提供了Callable接口,像是Runnable接口的增强版,Callable接口提供了一个 call()方法可以作为线执行体. call()方法比 ...

  5. 数据迁移最快方式,多线程并行执行 Sql插入

    前言: 由于系统升级,新开发的系统对数据验证,及数据关联做了很多优化,现需要将原历史版本的数据迁移到新系统中:原数据库大约有 1千多万数据,大约 50个表. 历史数据库命名为:A. 新系统库暂命名为 ...

  6. QThread 采用moveToThread方式实现多线程。 线程本身、connect关联的槽函数、connect关联的lambda对象分别运行在哪个线程中。

    Qt如何实现多线程:https://www.cnblogs.com/azbane/p/11372531.html September 5,2019 先抛出几个问题,用问题来引导思维导向: 1.继承的Q ...

  7. Android(java)学习笔记75:匿名内部类的方式实现多线程程序

    二话不说,首先利用代码体现出来,给大家直观的感觉: package cn.itcast_11; /* 4 * 匿名内部类的格式: 5 * new 类名或者接口名() { 6 * 重写方法; 7 * } ...

  8. java用Thread方式创建多线程

    进程:一个正在执行的程序,每一个进程都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元.线程:进程中一个独立的控制单元.线程控制着进程的执行.一个进程中至少有一个线程. java VM中至少有 ...

  9. SpringBoot几种定时任务的实现方式 和多线程执行任务

    定时任务实现的几种方式: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行, ...

随机推荐

  1. 坚果云创业团队访谈:我们 DIY 云存储(不要过度关注竞争对手,尤其当我们还是小公司的时候)

    坚果云(http://jianguoyun.com/)是一款用于多平台文件同步.备份和交换的云存储工具,立志于提供“便捷,安全”的服务.坚果云自去年年初启动内测,至今年三月初刚刚正式发布.近日我们拜访 ...

  2. 解决win8.1右键菜单出现在左边

    这个问题估计很少有人遇到,当在桌面上单击鼠标右键时,如果正常情况下,应该是在鼠标光标的右侧弹出来,除非右边的空间不够了,才在左侧弹出.但遇到故障,就是不论在桌面的哪里点右键,菜单都在左侧弹出,虽然不影 ...

  3. 使用Oracle的存储过程批量插入数据

    原文地址:http://www.cnblogs.com/liaoyu/p/oracle-procedure-batch-insert.html 作者:L君还在说之乎者也 最近在工作中,需要使用生成一些 ...

  4. Android java.net.SocketException四大异常解决方案

    java.net.SocketException如何才能更好的使用呢?这个就需要我们先要了解有关这个语言的相关问题.希望大家有所帮助.那么我们就来看看有关java.net.SocketExceptio ...

  5. (转载)NET流操作

    http://www.oseye.net/user/kevin/blog/86 概念 数据流(Stream)是对串行传输数据的一种抽象表示,是对输入/输出的一种抽象.数据有来源和目的地,衔接两者的就是 ...

  6. 转:Web service是什么?

    作者: 阮一峰 我认为,下一代互联网软件将建立在Web service(也就是"云")的基础上. 我把学习笔记和学习心得,放到网志上,欢迎指正. 今天先写一个最基本的问题,Web ...

  7. 微小说《tree》

    自己一直是一个矛盾纠结的人,计算机专业,却喜欢画画,偶尔会写些短文,寓言,或者酸酸的情诗.. 废话不多说,各位看官有兴趣便随意看看,若有些于共鸣,便共勉之. 正文 两株幼苗从土壤中破土而出,一颗天生强 ...

  8. Sublime Text SFTP 注册码,亲测有效,SVN注册码

    SFTP { "email": "xiaosong@xiaosong.me", "product_key": "d419f6-de ...

  9. MS-DOS 7.10完整安装版(含图文安装程序)

    大家知道,要想学习或使用DOS,安装一个DOS并进行实际操作是非常必要的.MS-DOS 7.10是一个非常好且强大实用的操作系统,而且兼容性和性能都十分强.要在系统中安装MS-DOS 7.10,可以使 ...

  10. ZOJ3732 Graph Reconstruction Havel-Hakimi定理

    分析: 给定一个非负整数序列{dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化. 进一步,若图为简单图,则称此序列可简单图化 (来自百度百科) 可简单图化的判定可以用Have ...