简单的C#线程开发实例(隔⼀秒改变⼀下Label的Text)
要实现的效果:点击按纽,窗⼝上的label上出现1~100数字的变化。
第⼀个实例(把窗⼝上的label上⽂字改成0):
using System;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
威力的近义词 {
public Form1(){InitializeComponent();}
private void Form1_Load(object nder, EventArgs e){label1.Text = "0";}
}
}
这个是最简单的实例,很容易。
第⼆个实例(点击button,循环显⽰0动态变化到100数字):
using System;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
public Form1(){InitializeComponent();}
private void Form1_Load(object nder, EventArgs e){label1.Text = "0";}
private void button1_Click(object nder, EventArgs e)
{
for(int i=0;i<101;i++){label1.Text = i.ToString();}
}
ppt转pdf }
}
运⾏⼀下,点击⼀下button1,没有看到0~100动态变化,就直接到了100了。原因:因为你的处理器速度太快了,就只能看到最后的结果。那么,怎样才能看到中间过程呢?
我们先⽤函数的⽅式来实现上⾯的功能,写个名为run的函数: private void run() { for(int i=0;i<101;i++){ label1.Text = i.ToString(); } }
深圳市最低工资这样就可以直接调⽤run函数实现功能了,⽽不⽤在事件函数内写代码。
第三个实例(使⽤函数):
using System;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
public Form1(){InitializeComponent();}
private void Form1_Load(object nder, EventArgs e){label1.Text = "0";}
private void run() { for(int i=0;i<101;i++){ label1.Text = i.ToString(); } }
private void button1_Click(object nder, EventArgs e){run();}
}
}
这⾥就需要在循环过程中加延时了,假定我们每隔1s的延时,lable1的值增加1,⽅法有很多。
⾸先我们⽤⼀个timer来实现延时。添加⼀个timer, 命名为timer1,在timer1的tick事件内添加语句,改变label1的值。(Tick事件是每经过指定时间间隔后被触发)。
第四个实例(使⽤timer),实现每隔1s的延时,lable1的值增加1,以达到动态变化的效果:
using System;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
int i; //全局变量
public Form1(){InitializeComponent();}
private void Form1_Load(object nder, EventArgs e){label1.Text = "0";}
private void run()
{
i = 0;
timer1.Interval = 1000; //设置timer1的间隔时间
timer1.Start(); //启动timer1
}
private void timer1_Tick(object nder, EventArgs e)
{
i++;
if (i > 100) {timer1.Stop();}
label1.Text = i.ToString();
}
private void button1_Click(object nder, EventArgs e) {run();}
}
}
我们运⾏⼀下,能够看到0~100循环的过程了。
以上是我们平常的做法,让label动态变化的效果,下⾯我们开始使⽤线程来实现上⾯的功能。
由于要使⽤多线程,我们需要引⽤using System.Threading;
过境签证通过下⾯的语句就定义⼀个名为thread1的线程 private Thread thread1;
和定义函数极为相似,定义线程之后,就要进⾏实例化: thread1 = new Thread(new ThreadStart(run));
这个语句的意思就是实例化thread1并将run函数设定为thread1的⼊⼝函数(⼤概意思就是,让run函数在线程thread1上执⾏)。
创建线程就算完成了,那么怎么运⾏线程呢?其实和启动timer1是类似的,thread1.Start();就运⾏了我们创建的线程thread1。
既然我们创建了线程,那么在关闭窗⼝的时候,就要撤消线程。添加FormClosing事件,在事件内部写如撤消线程的代码:
private void Form1_FormClosing(object nder, FormClosingEventArgs e)
{
if (thread1.IsAlive) //判断thread1是否存在,不能撤消⼀个不存在的线程,否则会引发异常
{ thread1.Abort(); //撤消thread1 }
}
这样才算⼤功告成,整理的代码如下:(在第三个实例的基础上加以改动)。
第五个实例:
using System;
using System.Threading;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
private Thread thread1;
public Form1(){InitializeComponent();}
private void Form1_Load(object nder, EventArgs e){label1.Text = "0";}
private void button1_Click(object nder, EventArgs e){thread1 = new Thread(new ThreadStart(run));thread1.Start();} private void run(){for (int i = 0; i < 101; i++){label1.Text = i.ToString();}}
private void Form1_FormClosing(object nder, FormClosingEventArgs e){if (thread1.IsAlive){thread1.Abort();}}
}参与式观察
}
运⾏⼀下,按button1,出错了,怎么回事呢?
看看出错原因,是在run函数内的label1.Text = i.ToString();语句上出的错,没错啊,语法正确啊。解释⼀下,出错的原因是为了保护数据的安全所以不能跨线程调⽤控件,⽽label1.Text = i.ToString();句则是在线程thread1上⾯调⽤主线程的控件,肯定会出错的!怎么办呢?⽤委托啊,我的理解就是,线程thread1不能调⽤主线程的lable1,所以,就委托主线程来改变lable1的值。⾸先看⼀个例⼦:(从例3改写)(并不创建线程,仅有主线程) 创建⼀个函数,⽤来设置lable1的值;
保护水资源图片
private void t_lableText(string s) { label1.Text = s; } 当需要改变lable1的值时,就调⽤它,并传递要改变的值。
第六个实例:
using System;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
public Form1(){InitializeComponent();}
private void Form1_Load(object nder, EventArgs e){label1.Text = "0";}势利小人
private void button1_Click(object nder, EventArgs e){run(); //调⽤run函数}
private void run(){for(int i=0;i<101;i++){t_lableText( i.ToString() );}}
private void t_lableText(string s){label1.Text = s;}
}
}
实现的功能与第三个实例是⼀样的,只是,增加了⼀个函数。
写人作文四百字到这⾥,需要了解⼀下委托这个东西,我们就需要委托主线程调⽤函数t_lableText(string s);来改变lable1的值。
⾸先声明⼀个委托: delegate void t_Text(string s);
创建⼀个全局委托变量: t_Text Set_Text;
进⾏实例化: Set_Text = new t_Text(t_lableText); //括号内的t_lableText是委托要调⽤的函数(也就是例6写的t_lableText(string s);函数)
现在,就剩下调⽤委托了,怎么调⽤委托呢?很简单。同过Invoke来调⽤,语句如下:
label1.Invoke(Set_Text, new object[] { i.ToString() }); //Set_Text是调⽤的委托,object[]则是我们要传递的参数
整理代码如下,第七个实例:
using System;
using System.Threading;
using System.Windows.Forms;
namespace ThreadTest
{
public partial class Form1 : Form
{
private Thread thread1; //定义线程
delegate void t_Text(string s); //定义委托
t_Text Set_Text; //定义委托变更
public Form1(){InitializeComponent();}
private void Form1_Load(object nder, EventArgs e){label1.Text = "0"; Set_Text = new t_Text(t_lableText); //实例化} private void button1_Click(object nder, EventArgs e){thread1 = new Thread(new ThreadStart(run)); thread1.Start();} private void t_lableText(string s){label1.Text = s;}//主线程调⽤的函数
private void run()
{
for (int i = 0; i < 101; i++)
{
label1.Invoke(Set_Text, new object[] { i.ToString() }); //通过调⽤委托,来改变lable1的值
Thread.Sleep(1000); //线程休眠时间,单位是ms
}
}
private void Form1_FormClosing(object nder, FormClosingEventArgs e)
{
if (thread1.IsAlive) //判断thread1是否存在,不能撤消⼀个不存在的线程,否则会引发异常 {thread1.Abort(); //撤消thread1}
}
}
}
这样,⼀个简单的多线程程序就算完成了。