多线程
线程:
一个进程相当于一个公司,一个进程默认只有一个主线程;
主线程主要控制窗体,如果你让他执行一段需要点时间的代码,那么窗体就没人控制了,就会出现程序假死情况;
线程,可以让程序同时干许多事,互相之间不冲突,不排队
线程启用:
Thread th = new Thread(需要执行的方法名称);
th.Start();//可以开始执行
前台线程:默认,当所有前台线程全部运行完毕后,进程才会结束
后台线程:当主窗体关闭后,所有后台线程就会自动关闭
设置方法: th.IsBackground = true;
关闭线程:th.Abort();
注意:线程关闭后就无法再次开启了
执行有参数的函数:
线程只能执行有一个参数,并且没有返回值的函数,而且这个参数必须是object类型;
参数的传递位置:th.Start(参数);
在winform中写一个简单的小程序来试验一下线程的使用以及注意事项
首先创建一个窗体,添加一个两个按钮和一个label控件,第一个按钮用来点击执行线程和关闭线程,第二个测试线程关闭后能否再重启label用来显示线程执行的方法
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.Windows.Forms; namespace 多线程 { public partial class Form1 : Form { public Form1() { InitializeComponent();
//默认线程不能访问主线程的东西,所以用下面的方法 Control.CheckForIllegalCrossThreadCalls = false;//关闭跨线程访问检查 } Thread th = null;//创建线程 private void button1_Click(object sender, EventArgs e) { th = new Thread(xunhuan);//启用线程,后面括号添加一个需要执行的方法名称 th.IsBackground = true;//将此线程设置为后台线程,当程序关闭时,线程也将关闭 th.Start();//开始执行 } public void xunhuan()//写一个方法 { for (int i = 1; i <= 10; i++)//从1循环显示到10 { label1.Text = i.ToString();//在设计界面添加的label控件中显示 Thread.Sleep(1000);//每隔一秒执行一次循环 .Sleep(时间)是指程序暂时沉睡的时间 if (i == 5)//加一个判断条件,如果循环显示到数字5, { //.Abort()终止线程 th.Abort();//则让线程停止,注意:线程停止后无法再开启,只有开启新的线程 } } } private void button2_Click(object sender, EventArgs e) { th.Start();//再添加一个按钮点击事件开始执行线程,试验一下已关闭的线程能否再开启 } } }
当点击第一个按钮后,label根据线程执行的方法从1 循环到5停止线程
当点击第二个按钮后,则无法重启已关闭线程
电话号码随机滚动小程序:
步骤:创建一个窗体,里面放上两个按钮,开始和停止按钮,在按钮点击事件中写方法,创建一个label控件,将随机出现的号码每循环一次赋值给label,形成滚动显示效果
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.Windows.Forms; namespace 多线程 { public partial class Form2 : Form { public Form2() { InitializeComponent(); //默认线程不能访问主线程的东西,则需要用下面的方法 Control.CheckForIllegalCrossThreadCalls = false;//关闭跨线程访问的检查 } Thread th = null; private void button1_Click(object sender, EventArgs e)//开始按钮的点击事件 { if (th != null)//此判断是可以重复点击这个按钮,点过第一次后每点一次,线程就会关闭,重新开始一个新的线程 { th.Abort(); } //定义一个字符串类型的数组放入一些号码 string[] nums = new string[]
{ "13864311111",
"13864322222",
"13864333333",
"13864344444",
"13864355555",
"13864366666", }; th = new Thread(suiji);//线程执行一下这个方法 th.IsBackground = true; th.Start(nums); } public void suiji(object n)//写一个方法给线程执行,此方法需要传一个object类型的参数,线程只能执行有一个参数,并且也没有返回值的函数 { string[] nums = n as string[];//传进来的参数为一个数组,用一个数组接一下 while (true)//一个无限循环 { Random r = new Random();//实例化一个随机数的方法 int ind = r.Next(nums.Length);//随机从0到这个数组元素个数-1,正好是所有元素的索引,用一个整数类型的变量接收 label2.Text = nums[ind];//每随机出一个数将它作为数组的索引,将label控件的text改为这个索引上的数值,这样一直循环 } } private void button2_Click(object sender, EventArgs e)//停止按钮的点击事件 { //当线程不等于空也就是已经开始执行了线程,点击停止才会关闭线程, //刚一进来线程还没有开始执行点击停止是无效的 if (th != null) { th.Abort(); } } //FormClosing事件,窗口关闭前发生的 private void Form2_FormClosing(object sender, FormClosingEventArgs e) { th.Abort();//当关闭窗口时先关闭线程,以免报错 } } }