---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ----------------------
测试准备:用vs2010创建WinForm程序
一、单线程的缺点
UI线程主要是负责跟用户交互打交道,主要监听用户操作如:拖动窗体、用户在文本框输入的值等。用户点击按钮后UI线程先响应用户点击按钮的操作调用里边的循环去了,没有线程去监听界面上的操作,就像售货员在上班时去做了别的事情用户来了没人接待一样。
二、多线程来解决问题
1、前期了解知识
线程相当于一个方法,在使用多线程时首先要将方法准备好。
多线程是由主线程开启的新的线程。
多线程是由主线程开启的新的线程,它是以时间换空间,具体的执行效率要看CPU。
步骤:引入命名空间—》创建线程方法--》传入要执行的方法(方法作为参数传,需要用到委托)
thread类的构造方法有两个:
public Thread(ParameterizedThreadStart start);
public Thread(ThreadStart start);
第一个是带参数的方法,第二个是不带参数的
2、不带参数的多线程
创建一个WinForm程序,在后台创建一个无返回值的方法
void CountTime()//创建方法
{
DateTime timestart = DateTime.Now;
for (int i = 0; i < 999999999; i++)
{
}
TimeSpan ts = timestart.Subtract(DateTime.Now);//从指定时间减去当前时间得到的时间差
MessageBox.Show("ThreadOver!"+ts.TotalMilliseconds);
}
在页面中拖一个按钮,它的点击事件如下:
private void btn_Multhread_Click(object sender, EventArgs e)
{
//多线程处理方法
//线程相当于一个方法,在使用多线程时首先要将方法准备好,将循环封装成一个方法。
Thread threadfirst = new Thread(CountTime);//方法作为参数传,需要用到委托
//定义public delegate void ThreadStart();返回值为空,所以多线程调用的方法返回值也应该为空
//多线程是由主线程开启的新的线程
threadfirst.Start();
}
3、方法重入问题
准备条件:在刚刚创建的WinForm窗体界面画出一个文本框、一个按钮,文本框的值默认为1
修改配置函数,关闭微软自带的检查:
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;//关闭检查
}
义一个无返回值的函数能够实现文本框的值得增长,并且在控制台打印出来执行的哪个线程、结果是什么、执行了多少次:
void changeText()
{
for (int i = 0; i < 1000; i++)
{
int a = int.Parse(txt_num.Text);
Console.WriteLine(Thread.CurrentThread+"a="+a);
a++;
txt_num.Text = a.ToString();
}
}
按钮点击事件:
private void btn_reset_Click(object sender, EventArgs e)
{
Thread thread = new Thread(changeText);
thread.Name = "t1";
thread.IsBackground = true;
thread.Start();
Thread thread2 = new Thread(changeText);
thread2.Name = "t2";
thread2.IsBackground = true;
thread2.Start();
}
理论上应出现的结果是2000,实际执行结果:1004。
原因:在线程t1还没执行完毕时,cpu开始执行t2,t2的值还是原来的的文本框的值,待t2还没执行完毕,cpu又开始执行t1…….
实际上是t1走了1000次,t2也执行了1000次
看控制台输出:(t1,t2是线程,a是执行时的值,i是执行次数)
t1,a=994,i=998
t2,a=995,i=993
t1,a=995,i=999
t2,a=996,i=994
t2,a=997,i=995
t2,a=998,i=996
t2线程 't2' (0x22b0) 已退出,返回值为 0 (0x0)。
,a=999,i=997
t2,a=1000,i=998
t2,a=1001,i=999
4、带参数的多线程
thread类的另外一个带参数的构造方法:
-------------------------执行带一参数的方法------------------------------
public Thread(ParameterizedThreadStart start);它的定义如下 public delegate void ParameterizedThreadStart(object obj);参数类型是object类型 void GetName(object name) { if (name != null) MessageBox.Show("name=" + name.ToString()); else MessageBox.Show("null"); } private void btn_threadWithParm_Click(object sender, EventArgs e) { //ParameterizedThreadStart pts = new ParameterizedThreadStart(GetName);//声明带参数的委托 //Thread thread = new Thread(pts); //执行带参数的方法 Thread thread = new Thread(GetName);//直接把方法写进去 thread.IsBackground = true; thread.Start(txt_name.Text);//start也有两种类型,其一是带参数的 }
//-------------------------执行带多个参数的方法------------------------- void GetName2(object li) { List<string> list = li as List<string>;//泛型方法 if (list != null) { foreach (var s in list) { MessageBox.Show(s); } } } private void btn_WithManyParam_Click(object sender, EventArgs e) { Thread thread = new Thread(GetName2); thread.IsBackground = true; thread.Start(new List<string> {"张三","李四","王五"}); }
---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ----------------------