C#多线程demo

65 篇文章 0 订阅
首先,我们写个简单的单线程程序,也就是只有程序自己创建的那个主线程,没有使用多线程.
 
创建一个新工程,向窗口添加一个label命名为label1;我们要让程序运行时label1就显示一个数字,假设为100;通常我们会直接在窗口加载事件中写label1.Text = “100″;这样,运行
 
,label1果然显示了100;
 
代码如下:(例1)
 
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,命名为button1,我们要在按下button1后,将lable1的text从0显示到100,
那么,我们需要添加button1的Click事件,在click事件内写入循环显示0到100.
 
代码如下:(例2)
 
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();
}
}
}
}
 
运行一下看看,按一下button1,结果是我们一下就看到了100,并没有看到0~100的过程,为什么呢?
呵呵,因为你的处理器速度太快了,就只能看到最后的结果,那么,怎样才能看到中间过程呢?(等一下再讲)
我们先用函数的方式来实现上面的功能
写个名为run的函数吧:
private void run()
{
for(int i=0;i<101;i++)
{
label1.Text = i.ToString();
}
}
这样就可以直接调用run函数实现功能了,而不用在事件函数内写代码。(这样做是有好处的)
 
整个代码如下:(例3)
 
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();
}
}
}
}
 
这里就需要在循环过程中加延时了,假定我们每隔1s的延时,lable1的值增加1。
方法有很多,我们就用一个timer来实现延时。
 
添加一个timer, 命名为timer1,在timer1的tick事件内添加语句,改变label1的值。(Tick事件是每经过指定时间间隔后被触发)
 
代码如下:(例4)
 
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循环的过程了。
 
下面我们就要进入多线程了,不知道各位将上面的内容看懂了没有?
 
开始进入多线程之前我还是先简单的说说定义线程吧。(与多线程有关的其它内容我就不说了吧,那个太多太多了)
由于要使用多线程,我们需要引用System.Threading;所以之后的代码都会在前面加上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 sender, FormClosingEventArgs e)
{
if (thread1.IsAlive) //判断thread1是否存在,不能撤消一个不存在的线程,否则会引发异常
{
thread1.Abort(); //撤消thread1
}
}
 
这样才算大功告成嘛,整理的代码如下:(例5)(在例3的基础上加以改动)
 
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的值时,就调用它,并传递要改变的值。
 
整理代码如下:(例6)
 
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;
}
}
}
 
实现的功能与例3是一样的,只是,增加了一个函数。
 
现在再来看看委托,我们就需要委托主线程调用函数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)
 
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#多线程与Socket编程 在程序设计中,涉及数据存储和数据交换的时候,不管是B/S还是C/S模式 ,都有这样一个概念:数据库服务器。这要求一台性能和配置都比较好的主机作为服务器, 以满足数目众多的客户端进行频繁访问。但是对于一些数据交换的要求不主同,而且涉及到的通讯个体数目不多,如果还采用“一主机多客户机”的模式, 便要求一台硬件配置良好而且软件上安装了相关数据服务软件,这样会造成硬件和软件上的很多不必要的成本,这时Socket在点对点的平行对象之间的网络通讯的优势就就发挥出来了。 其实对于Socket通讯来说,服务器和客户端的界定不像数据库服务器与客户端那样明显,甚至可以说Socket通讯里面的服务器和客户端只是相对的, 因为网络通讯的对象基本上是处于平等层面的,只是为了方便对两台联网通讯的主机的描述才这样定义称谓的。 由于在.NET中Socket通讯的建立很容易,所以本文主要介绍一个Socket的比较典型的应用的流程:客户端向服务器发送图片请求,图片服务器接收到请求, 并将服务器硬盘上的图片编码,发送到客户端,客户端得到图片数据后,再将这些数据写成图片文件,保存在客户端上。 本文主要是对Socket的一个应用进行介绍,所以至于其原理在此没有深究,至于如何建立Socket还有如何实现网络的七层协议在此都没有进行相关研究和介绍, 本文主要介绍如何实现一个用户想要的功能,即在两台主机之间进行通讯,通过网络来收发用户想要收发的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值