C#线程开发:winform简单的C#线程开发实例
来源:互联网 发布:千里眼监控软件客户端 编辑:程序博客网 时间:2024/06/06 08:23
一直想弄清楚线程是如何工作的,一直在找相关的实例都没有找到,没有找到容易看懂的实例。今天终于找到一个,觉得很简单,把它转到这里来分享一下。
要实现的效果是:
点击按纽,窗口上的label上出现1~100数字的变化。
窗口上有两个控键,一个label,一个button。
第一个实例(把窗口上的label上文字改成100):
using System;using System.Windows.Forms;namespace ThreadTest{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { label1.Text = "100"; } }}
这个是最简单的实例,应该不难看懂。
第二个实例(点击button,循环显示0动态变化到100数字):
using System;using System.Windows.Forms;namespace ThreadTest{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { label1.Text = "0"; } private void button1_Click(object sender, EventArgs e) { for(int i=0;i<101;i++) { label1.Text = i.ToString(); } } }}
原因:因为你的处理器速度太快了,就只能看到最后的结果,那么,怎样才能看到中间过程呢?
我们先用函数的方式来实现上面的功能
写个名为run的函数吧:
private void run(){ for(int i=0;i<101;i++) { label1.Text = i.ToString(); }}
整个代码如下:
using System;using System.Windows.Forms;namespace ThreadTest{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { label1.Text = "0"; } private void button1_Click(object sender, EventArgs e) { run(); //调用run函数 } private void run() { for(int i=0;i<101;i++) { label1.Text = i.ToString(); } } }}
方法有很多,我们就用一个timer来实现延时。
添加一个timer, 命名为timer1,在timer1的tick事件内添加语句,改变label1的值。(Tick事件是每经过指定时间间隔后被触发)
using System;using System.Windows.Forms;namespace ThreadTest{ public partial class Form1 : Form { int i; //全局变量i public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { label1.Text = "0"; } private void button1_Click(object sender, EventArgs e) { run(); } private void run() { i = 0; timer1.Interval = 1000; //设置timer1的间隔时间 timer1.Start(); //启动timer1 } private void timer1_Tick(object sender, EventArgs e) //timer1的Tick事件 { i++; if (i > 100) { timer1.Stop(); } label1.Text = i.ToString(); } }}
同样的,我们运行一下,看看结果,很好,我们能够看到0~100循环的过程了。
以上是我们平常的做法,让label动态变化的效果,下面我们开始使用线程来实现上面的功能。
通过下面的语句就定义一个名为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 sender, 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 sender, EventArgs e) { label1.Text = "0"; } private void button1_Click(object sender, 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 sender, 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 set_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 sender, EventArgs e) { label1.Text = "0"; } private void button1_Click(object sender, EventArgs e) { run(); //调用run函数 } private void run() { for(int i=0;i<101;i++) { set_lableText( i.ToString() ); } } private void set_lableText(string s) { label1.Text = s; } }}
实现的功能与第三个实例是一样的,只是,增加了一个函数。
到这里,需要了解一下委托这个东西,我们就需要委托主线程调用函数set_lableText(string s);来改变lable1的值。
首先声明一个委托:
delegate void set_Text(string s);
创建一个全局委托变量:(应该是变量吧)
set_Text Set_Text; //请注意大小写,set_Text是委托类型,Set_Text是创建的委托(当然,这里的命名是随意的)
类似于创建线程,需要进行实例化:
Set_Text = new set_Text(set_lableText); //括号内的set_lableText是委托要调用的函数(也就是例6写的set_lableText(string s);函数)
现在,就剩下调用委托了,怎么调用委托呢?很简单。
同过Invoke来调用,语句如下:
label1.Invoke(Set_Text, new object[] { i.ToString() });
//Set_Text是调用的委托,object[]则是我们要传递的参数
整理代码如下:(例7)
第七个实例:使用多线程实现0~100动态变化效果
using System;using System.Threading;using System.Windows.Forms;namespace ThreadTest{ public partial class Form1 : Form { private Thread thread1; //定义线程 delegate void set_Text(string s); //定义委托 set_Text Set_Text; //定义委托 public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { label1.Text = "0"; Set_Text = new set_Text(set_lableText); //实例化 } private void button1_Click(object sender, EventArgs e) { thread1 = new Thread(new ThreadStart(run)); thread1.Start(); } private void set_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 sender, FormClosingEventArgs e) { if (thread1.IsAlive) //判断thread1是否存在,不能撤消一个不存在的线程,否则会引发异常 { thread1.Abort(); //撤消thread1 } } }}
这样,一个简单的多线程程序就算完成了。
- C#线程开发:winform简单的C#线程开发实例
- C#线程开发:winform简单的C#线程开发实例
- c# 线程简单实例
- c# winform开发 从线程中访问控件
- 胡侃软件开发之C#的线程
- c# 最简单的线程
- C#线程池实例
- C# 线程创建实例
- C#线程编程实例
- c# 线程操作实例
- c#线程池实例
- c# 开发winform控件
- c# 开发winform控件
- C# WinForm开发系列
- C# WinForm开发系列
- C# WinForm开发系列
- C# WinForm开发系列
- C# WinForm开发框架
- pat 1013. Battle Over Cities (25)
- 黑马学习笔记——怎么让Div自适应高度
- VS2010项目重命名
- UVa 10739 - String to Palindrome
- 算法学习笔记之堆排序
- C#线程开发:winform简单的C#线程开发实例
- [转]你应该更新的Java知识之Optional高级用法
- 关于前端的一些心得
- 高管离职的25个原因
- c++相关机器学习库
- netty1
- Selenium_python 方法调用
- 单点登录配置
- Android的系统架构