在System.Threading命名空间下,有一个Thread类,用于对线程进行管理,如创建线程、启动线程、终止线程、合并线程、让线程休眠等
firTh.IsBackground 返回一个bool值,判断或设置是否属于后台线程
默认情况下,属于托管线程池的线程(即IsThreadPoolThread为true)都属于后台线程,而通过创建并启动新的Thread对象生成的都属于前台线程。
如果使用一个线程监视某些活动(如Socket),可以将IsBackground设置为true,以遍该线程不会影响进程终止。
1、启动线程
Thread t1 = new Thread(方法名); //创建一个线程,该线程通过委托执行指定的方法,从.net2.0开始可以这么写,否则需要加ThreadStart
如果该方法带有参数,可以在启动时传递:
t1.Start(); //无参
t1.Start("I'm param"); //有参数
参数只能有一个,只能是object类型,如果希望传递多个,可以把所有参数封装到一个类,再传该类的实例。
2、终止线程
有两种方法,第一种是事先设置一个bool值,在其他线程修改这个bool值表示是否需要终止,在该线程中循环判断该布尔值,以确定是否需要退出该线程。
第二种是调用Abort()方法,该方法的最终效果是强行终止该线程。但线程实际上不一定会立即结束,因为系统在结束线程前要进行代码清理工作,这需要一定的时间,因此在调用Abort()方法后,如果自动清理工作还未结束,可能会出现类似于死机的假死现象。为了解决这个问题,可以在主线程中调用Join()方法,并在Join方法中指定主线程等待子线程结束的等待时间。
推荐第一种方法,实际工作中也是一般使用第一种方法。
3、暂停线程
Thread.Sleep(int 毫秒) 该方法为静态方法
4、合并线程
t1.Join();
如果线程t1需要在线程t2执行结束才继续执行,可以在t1中调用t2.Join(),但是如果t2一直不执行完,那么t1也无法执行,因此可以给Join加一个参数:
t1.Join(1000); 这样t1至多只会等待1000毫秒,然后无论t2是否结束,都继续往下执行。
在一个线程中访问由另一个线程创建的控件
直接访问会报异常:从不是创建控件的线程访问它。 现在有两种办法可以实现这个功能:
第一种是使用委托和事件完成。
第二种是利用BackroundWorker组件实现。
1. 委托
首先在类里面定义一个委托
然后在需要用到的地方实例化委托
通过控件的InvokeRequired判断该控件是否属于该线程,并使用委托或者直接调用需要的方法:
public partial class Form1 : Form { delegate void ToAddSth(string item); //在类中定义委托 ... private void AddMessage(string item) { ToAddSth myDele = new ToAddSth(AddMessage); //实例化委托 if(TextBox1.InvokeRequired) //根据控件的InvokeRequired判断是否需要委托 { TextBox1.Invoke(myDele,item); //利用委托 } else { TextBox1.Items.Add(item); //直接调用 } } }
2.BackgroundWorker
这个控件被实例化后,一般会用到其两个属性和三个方法:
bw1.WorkerReportsProgress = true; //设置能否报告进度更新
bw1.WorkerSupportsCancellation = true; //设置是否支持异步取消
bw1.DoWork += SayHello; //异步执行的事件,可用bw1.RunWorkerAsync() 方法启动该事件
bw1.ProgressChanged += ShowTime; //显示最新数据到窗体上的事件,可用bw1.ReportProgress(0, object) 方法调用该事件
bw1.RunWorkerCompleted += GameOver; //停止DoWork事件时 发生的事件。用bw1.CancelAsync() 调用该事件
BackgroundWorker backgroundWorker1; public Form1() { InitializeComponent(); backgroundWorker1 = new BackgroundWorker(); backgroundWorker1.WorkerReportsProgress = true; backgroundWorker1.WorkerSupportsCancellation = true; backgroundWorker1.DoWork += background1_DoWork; backgroundWorker1.ProgressChanged += background1_ProcessChanged; backgroundWorker1.RunWorkerCompleted += background1_RunWorkerCompleted; button2.Enabled = false; } private void button1_Click(object sender, EventArgs e) { richTextBox1.Text = "开始产生10000以内的随机数…\r\n"; button1.Enabled = false; button2.Enabled = true; backgroundWorker1.RunWorkerAsync(); } private void button2_Click(object sender, EventArgs e) { backgroundWorker1.CancelAsync(); button1.Enabled = true; button2.Enabled = false; } private void background1_DoWork(object sender, DoWorkEventArgs e) { Random r=new Random(); BackgroundWorker bgw1 = sender as BackgroundWorker; int numCount = 0; while (!bgw1.CancellationPending) { int num = r.Next(10000); if (num % 5 == 0) { numCount++; } bgw1.ReportProgress(0, num); Thread.Sleep(100); } e.Result = numCount; } private void background1_ProcessChanged(object sender, ProgressChangedEventArgs e) { int num = (int)e.UserState; richTextBox1.Text += num + " "; } private void background1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error == null) { richTextBox1.Text += "\r\n操作停止,共产生 " + e.Result + " 个能被5整除的数!"; } else { richTextBox1.Text += "\r\n操作错误:" + e.Error; } }