39.多线程
时间:2020-05-28
本文章向大家介绍39.多线程,主要包括39.多线程使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
为什么要用多线程
- 让计算机"同时"做多件事情,节约时间。
- 多线程可以让一个程序“同时”处理多个事情。
- 后台运行程序,提高程序的运行效率,也不会使主界面出现无响应的情况。
- 获得当前线程和当前进程
如何实现多线程?
- 编写产生线程所要执行的方法
- 引用System.Threading命名空间
- 实例化Thread类,并传入一个指向线程所要运行方法的委托。(这时候这个线程已经产生,但是还没有运行)
- 调用Thread实例的Start方法,标记该线程可以被CPU执行了,但具体执行时间由CPU决定。
前台线程和后台线程
前台线程
只有所有的前台线程都关闭才能完成程序关闭。主线程也是前台线程
后台线程
只要所有的前台线程结束,后台线程自动结束。
实现
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp8 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
//创建一个线程去执行这个方法,默认情况下新创建的线程都是前台线程
Thread th = new Thread(Test);
//标记这个线程准备就绪了,可以随时被执行。具体什么时候执行这个线程,
//由cpu决定
//将线程设置为后台线程
th.IsBackground = true;
th.Start();
}
private void Test() {
for (int i = 0; i < 500000; i++) {
Console.WriteLine(i);
}
}
}
}
当创建的线程为前台线程时,会出现如下图所示现象,当关闭窗体时,创建的那个线程依旧在执行。而当将此线程设为后台线程后,就不会出现这种现象了。
在.Net下,是不允许跨线程的访问。
例如:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp8 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
//创建一个线程去执行这个方法,默认情况下新创建的线程都是前台线程
Thread th = new Thread(Test);
//标记这个线程准备就绪了,可以随时被执行。具体什么时候执行这个线程,
//由cpu决定
//将线程设置为后台线程
//th.IsBackground = true;
th.Start();
}
private void Test() {
for (int i = 0; i < 10000; i++) {
//Console.WriteLine(i);
textBox1.Text = i.ToString();
}
}
}
}
运行:
textbox1控件是由主线程创建的,它所在的Test()方法被新线程执行了,当创建的新线程想要访问另一个线程(主线程)中的资源时,应用程序并不允许这样做。在.Net下,是不允许跨线程的访问。
可以这样进行修改
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp8 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
//创建一个线程去执行这个方法,默认情况下新创建的线程都是前台线程
Thread th = new Thread(Test);
//标记这个线程准备就绪了,可以随时被执行。具体什么时候执行这个线程,
//由cpu决定
//将线程设置为后台线程
//th.IsBackground = true;
th.Start();
}
private void Test() {
for (int i = 0; i < 10000; i++) {
//Console.WriteLine(i);
textBox1.Text = i.ToString();
}
}
private void Form1_Load(object sender, EventArgs e) {
//取消跨线程的访问的限制
//Control是winform中控件的基类
//CheckForIllegalCrossThreadCalls:指示是否捕获对错误线程的调用
Control.CheckForIllegalCrossThreadCalls = false;
}
}
}
但是当关闭程序时,有时也会出现问题如下图。
出现这种问题的原因是:虽然关闭了程序,但由于种种原因,新线程并没有马上关闭,也就意味着新线程还会访问textbox1,但是主线程一关,资源将被释放掉,textbox1也就不存在了,新线程就访问不到textbox1了。
所以可以在关闭程序时判断下这个新线程是否为null,如果这个新线程th为null,那么就是主线程结束了,这个新线程也结束了。如果不为null,那么意味着主线程虽然关了,但由于某些原因,新线程并没有马上关闭,这时我们可以手动的进行关闭。
解决:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp8 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
Thread th;
private void button1_Click(object sender, EventArgs e) {
//创建一个线程去执行这个方法,默认情况下新创建的线程都是前台线程
th = new Thread(Test);
//标记这个线程准备就绪了,可以随时被执行。具体什么时候执行这个线程,
//由cpu决定
//将线程设置为后台线程
//th.IsBackground = true;
th.Start();
}
private void Test() {
for (int i = 0; i < 10000; i++) {
//Console.WriteLine(i);
textBox1.Text = i.ToString();
}
}
private void Form1_Load(object sender, EventArgs e) {
//取消跨线程的访问
//Control是winform中控件的基类
//CheckForIllegalCrossThreadCalls:指示是否捕获对错误线程的调用
Control.CheckForIllegalCrossThreadCalls = false;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
//当你点击关闭窗体的时候,判断新线程是否为null
if (th != null) {
//结束这个线程,线程被Abort后就不能再重新Start了
th.Abort();
}
}
}
}
注意 如果线程执行的方法需要参数,那么要求这个参数必须是object类型.
private void button1_Click(object sender, EventArgs e)
{
Thread th = new Thread(Test);
th.IsBackground = true;
th.Start("123");
//Test();
}
private void Test(object s){
string ss = (string)s;
for (int i = 0; i < 10000; i++){
Console.WriteLine(i);
}
}
方法
Start():启动线程(告诉CPU 我可以被执行了,具体什么时候执行,由CPU决定)
Abort():终止线程 终止完成之后不能再Start()
Thread.Sleep() 静态方法,可以使当前线程停止一段时间运行
Thread.CurrentThread:获得当前的线程引用
原文地址:https://www.cnblogs.com/lz32158/p/12977574.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于docker搭建gitlab
- 理解Future及FutureTask的实现
- centos7 hbase1.4.13+hadoop2.7.1+单机环境搭建
- 关于kubeconfig多集群切换
- 代码版本管理规范
- 基于云原生系统的应用分发系统设计
- vue实现文字表情同时输入的方法
- 不同类型的ABAP内表读写性能比较
- JavaScript和ABAP的MD5计算源代码
- 读取SAP CRM One Order应用日志的优化方式
- 悟空活动中台 - 基于 WebP 的图片高性能加载方案
- DES ECB加解密的Java实现
- win10 uwp 不显示 SplashScreen 欢迎界面的方法
- WPF 在 XAML 写 C# 代码
- 解析 HashMap源码值概括