您的位置:首页 > 职场人生

黑马程序员(1)---初学多线程

2013-07-06 19:57 190 查看
---------------------- 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培训、期待与您交流! ----------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: