【.NET线程--进阶(一)】--线程方法详解
上篇博客从线程的基本概况开始着重讨论了线程,进程,程序之间的区别,然后讨论了线程操作的几个类,并通过实例来说明了线程的创建方法。本篇博客将会带大家更深入的了解线程,介绍线程的基本方法,并通过一个Demo使用委托来调用线程之外的对象。
前篇博客基础:【GDI+编程--番外篇(二)】--从事件看委托
【.NET线程--开篇】--线程从零开始
线程
多线程优缺点
多线程的使用会帮助程序提高响应速度,因为可以同时执行多个任务这样对比一个个的来完成任务来说提高了响应的速度,较之添加多CPU来说多线程提高了强大的技术来执行多个任务。虽然多线程提高了响应速度,但同时牺牲了资源,由于多线程的执行它会占用多个资源,为了避免资源访问的冲突,往往会在每个线程中都会创建自己的资源,这样导致了资源的浪费。另外如果线程过多,则其中大多数线程都不会产生明显的进度,如果大多数当前线程处于一个进程中,则其他进程中的线程的调度频率就会很低。
线程基本方法
下表包括了在线程编程过程中常用的基本方法。
可用于控制单个线程的方法
| 方法 | 操作 |
|---|---|
| Start | 使线程开始运行。 |
| Sleep | 使线程暂停指定的一段时间。 |
| Suspend | 在线程到达安全点时,使其暂停。 |
| Abort | 在线程到达安全点时,使其停止。 |
| Resume | 重新启动挂起的线程 |
| Join | 使当前线程一直等到另一线程完成。 在与超时值一起使用时,如果该线程在分配的时间内完成,此方法将返回 True。 |
Note: 安全点是指代码中公共语言运行时可以安全地执行自动“垃圾回收”的位置。垃圾回收是指释放不再使用的变量并回收内存的过程。 调用线程的 Abort 或 Suspend 方法时,公共语言运行时将对代码进行分析,确定让线程停止运行的适当位置。
Demo1:线程,方法--委托
自己做的一个小Demo来实现多线程,当点击开始按钮后会在文本框中填写数字,与此同时加载进度条,读取进度,点击暂停后线程会停止。另外可以在文本框中输入暂停时间来指定线程暂停时间,在暂停后继续执行。
Demo下载地址:线程常用方法示例
在点击开始按钮后会同时创建两个线程,分别为showNumThread和pBarThread,用来向文本框中写入数字和加载进度条。这里需要说明的是,一般情况下线程内部是不允许调用线程外创建的对象的,创建的两个线程都调用了线程外部的对象,是怎么实现的呢?使用的是委托来异步执行程序来实现了调用线程外部的方法。
- /// <summary>
- /// 开始按钮事件,创建线程并为线程指定方法
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btnStart_Click(object sender, EventArgs e)
- {
- pBarThread = new Thread(new ThreadStart(this.ExepBarShow)); //创建进度条线程
- showNumThread = new Thread(new ThreadStart(this.ExeShowNum)); //创建显示文本框中的文字线程
- //开始两个已创建的线程
- this.StartThread(showNumThread);
- this.StartThread(pBarThread);
- }
- /// <summary>
- /// 使用委托执行ShowNumToText方法
- /// </summary>
- private void ExeShowNum()
- {
- try
- {
- MethodInvoker mInvoker = new MethodInvoker(this.ShowNumToText); //声明托管委托,并为委托执行执行的方法
- //执行委托方法,向Text中写入文字
- while (true)
- {
- this.BeginInvoke((Delegate)mInvoker); //异步执行执行的委托
- Thread.Sleep(1000); //线程停顿1秒后继续执行
- }
- }
- catch { }
- }
- /// <summary>
- /// 先文本框txtNum中写入文字
- /// </summary>
- private void ShowNumToText()
- {
- i = i + 1; //i累加
- txtNum.Text = txtNum.Text + " " + (i + 1).ToString(); //向txtNum中写入文字
- }
- /// <summary>
- /// 执行pBarShow方法,加载进度条,让进度条读取进度
- /// </summary>
- private void ExepBarShow()
- {
- try
- {
- MethodInvoker mInvoker = new MethodInvoker(this.pBarShow); //声明并创建委托,为委托执行进度
- //异步执行委托
- while (true)
- {
- this.BeginInvoke((Delegate)mInvoker);
- Thread.Sleep(10);
- }
- }
- catch { }
- }
- /// <summary>
- /// 执行进度条读取进度
- /// </summary>
- private void pBarShow()
- {
- this.pgBar.PerformStep();
- }
- /// <summary>
- /// 线程开始方法
- /// </summary>
- /// <param name="th">Thread对象,需要开始的线程</param>
- private void StartThread(Thread th) {
- th.Start();
- }
- /// <summary>
- /// 线程结束方法
- /// </summary>
- /// <param name="th">Thread对象,需要结束的线程</param>
- private void EndThread(Thread th) {
- th.Interrupt(); //中断线程
- th.Abort(); //终止线程
- th = null;
- }
- /// <summary>
- /// 停止线程事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btnStop_Click(object sender, EventArgs e)
- {
- try
- {
- this.TestThead(); //验证线程是否存在,如果没有存在将会抛错
- this.EndThread(this.pBarThread); //结束线程
- this.EndThread(this.showNumThread); //结束线程
- }
- catch (Exception ex)
- {
- //提示错误信息
- MessageBox.Show(ex.Message , "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- }
- }
- /// <summary>
- /// 终止线程事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btnEnd_Click(object sender, EventArgs e)
- {
- try
- {
- this.TestThead(); //验证线程是否创建
- this.EndThread(this.pBarThread);//结束线程
- this.EndThread(this.showNumThread); //结束线程
- txtNum.Text = ""; //清空文本框内容
- i = 0; //数字充值
- this.pgBar.Value = 0;//进度条重置
- }
- catch (Exception ex)
- {
- //显示错误信息
- MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- }
- }
- /// <summary>
- /// 执行指定线程停顿时间
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btnStopMinute_Click(object sender, EventArgs e)
- {
- try
- {
- int j = int.Parse(textBox1.Text); //获取终止的时间
- Thread.Sleep(j); //将线程暂停指定的时间
- }
- catch (Exception ex)
- {
- MessageBox.Show(ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- }
- }
- /// <summary>
- /// 验证线程是否存在方法
- /// </summary>
- private void TestThead() {
- if (pBarThread ==null)
- {
- throw new Exception ("未创建线程,请创建线程后操作!");
- }
- if (showNumThread == null)
- {
- throw new Exception ("未创建线程,请创建线程后操作!");
- }
- }
Demo2:Join方法使用实例
Join方法能在指定的线程中插入一个线程,当插入的线程执行完成后才会继续执行被插入的线程。.NET为我们重载了此方法,能够为方法传递参数来指定经过的时间,此时该方法的作用与Sleep相类似,执行经过多长时间后来执行被插入的线程。Join方法的灵活运行能够实现线程之间的执行顺序。
- using System;
- using System.Threading;
- namespace TestJoin
- {
- /// <summary>
- /// Join方法验证实例,线程t1使用了join方法,线程t2没有使用join方法
- /// </summary>
- class Program
- {
- static void Main(string[] args)
- {
- //创建新线程,为线程执行行为
- Thread t1 = new Thread(() =>
- {
- Thread.Sleep(1000);
- Console.WriteLine("t1 is ending.");
- });
- t1.Start(); //开始线程
- t1.Join(); //在主线程中插入t1线程,先执行t1,线程后执行主线程
- Console.WriteLine("t1.Join() returned."); //执行主线程,提示t1已经完成
- //创建新线程,为线程执行行为
- Thread t2 = new Thread(() =>
- {
- Thread.Sleep(1000);
- Console.WriteLine("t2 is ending.");
- });
- t2.Start(); //开始线程
- Console.WriteLine("t2.Join() returned."); //执行主线程,提示t1已经完成
- Console.ReadLine();
- }
- }
- }
- /*输出结果:
- *t1 is ending.
- *t1.Join() returned.
- *
- *t2.Join() returned.
- *t2 is ending.
- */
输出结果:
从输出结果上分析可以得出,Join方法将创建的线程插入到了主线程中当执行完后再继续执行主线程,对应到Demo2中是线程t1插入到了主线程中,这样会首先执行t1线程在控制台上打印“t1 is ending”打印完成后t1线程结束,然后继续执行主线程来打印其它的文字。所以我们完全可以说Join方法是将一个线程插入到主线程中,当执行完插入的线程后再继续执行被插入的线程。
结语
线程的优缺点决定了在开发过程中是否使用多线程,另外灵活运行单线程的方法来实现灵活的控制线程,两个Demo使用了线程的基本方法,能够更加深刻的了解它们的使用。下篇博客将会更加深入的讨论线程和线程之间的调用关系,以及如何实现线程间的数据传递及检索。
【.NET线程--进阶(一)】--线程方法详解的更多相关文章
- MySQL服务器线程数的查看方法详解
本文实例讲述了MySQL服务器线程数的查看方法.分享给大家供大家参考,具体如下: mysql重启命令: ? 1 /etc/init.d/mysql restart MySQL服务器的线程数需要在一个合 ...
- (二)线程Thread中的方法详解
1.start() start()方法的作用讲得直白点就是通知"线程规划器",此线程可以运行了,正在等待CPU调用线程对象得run()方法,产生一个异步执行的效果.通过start( ...
- 线程Thread中的方法详解(二)
1.start() start()方法的作用讲得直白点就是通知"线程规划器",此线程可以运行了,正在等待CPU调用线程对象得run()方法,产生一个异步执行的效果.通过start( ...
- “全栈2019”Java多线程第十二章:后台线程setDaemon()方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第七章:等待线程死亡join()方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第六章:中断线程interrupt()方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第五章:线程睡眠sleep()方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- java多线程并发(二)--线程的生命周期及方法详解
上篇随笔介绍了线程的相关基础知识以及新启线程的几种方法,本片将继续介绍线程的生命周期及方法详解. 一.线程的生命周期 在Thread代码中,线程的状态被分为6种 public enum State { ...
- 并发编程(六)Object类中线程相关的方法详解
一.notify() 作用:唤醒一个正在等待该线程的锁的线程 PS : 唤醒的线程不会立即执行,它会与其他线程一起,争夺资源 /** * Object类的notify()和notifyAll()方法详 ...
- java线程池的使用与详解
java线程池的使用与详解 [转载]本文转载自两篇博文: 1.Java并发编程:线程池的使用:http://www.cnblogs.com/dolphin0520/p/3932921.html ...
随机推荐
- js闭包之应用场景
闭包的解释 当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行,这时就产生了闭包 在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义 ...
- js计时器 setInterval与clearInterval
var timer = setInterval(函数, 毫秒数) 功能:每隔对应的毫秒数执行一次函数. 返回值:系统没启动一个定时器,就会给一个标识,返回值就是这个定时器的编号. clearInter ...
- 《剑指offer》-数组中只出现一次的数字
/* 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 思路: 如果是只有一个数字出现一次,那么所有数字做异或就得到结果: 现在有两个数字x,y分别出现一次 ...
- 怎么用pr(Premiere)给视频添加水印
自己辛辛苦苦剪切的视频,不添加水印,别人肯定会搬走的,作为对视频付出时间的你肯定不想看见这样的事情,下面一起来看看怎么用pr给视频添加水印吧 工具/原料 水印 pr 方法/步骤 首先打 ...
- [转] Java中public,private,final,static等概念的解读
作为刚入门Java的小白,对于public,private,final,static等概念总是搞不清楚,到底都代表着什么,这里做一个简单的梳理,和大家分享,若有错误请指正,谢谢~ 访问权限修饰符 pu ...
- 【AtCoder】ARC078
C - Splitting Pile 枚举从哪里开始分的即可 #include <bits/stdc++.h> #define fi first #define se second #de ...
- HTTP协议学习笔记(一)
HTTP协议学习笔记(一) 1.HTTP协议用于客户端和服务端之间的通信 客户端:请求访问文本或图像等资源的一端服务端:提供资源响应的一端 在两台计算机之间使用HTTP协议通信时,在一条通信线路上必定 ...
- 算法进阶面试题04——平衡二叉搜索树、AVL/红黑/SB树、删除和调整平衡的方法、输出大楼轮廓、累加和等于num的最长数组、滴滴Xor
接着第三课的内容和讲了第四课的部分内容 1.介绍二叉搜索树 在二叉树上,何为一个节点的后继节点? 何为搜索二叉树? 如何实现搜索二叉树的查找?插入?删除? 二叉树的概念上衍生出的. 任何一个节点,左比 ...
- 三篇文章带你极速入门php(三)之php原生实现登陆注册
看下成果 ps:纯天然h5,绝不添加任何添加剂(css)以及化学成分(js)(<( ̄ ﹌  ̄)我就是喜欢纯天然,不接受任何反驳) 关于本文 用原生的php和html做了一个登陆注册,大概是可以窥 ...
- Thread中的一些方法
Thread中的一些方法: currentThread() 返回对当前正在执行的线程对象的引用(实现接口方式时使用). sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠( ...