多数情况下,可以不用new ThreadStart委托。直接在构造函数里传入void类型的方法。
Thread t = new Thread (Go);
使用lambda表达式
static void Main()
{
Thread t = new Thread ( () => Console.WriteLine ("Hello!") );
t.Start();
}
Foreground线程和Background线程
默认情况下创建的线程都是Foreground,只要有一个Foregournd线程在执行,应用程序就不会关闭。
Background线程则不是。一旦Foreground线程执行完,应用程序结束,background就会强制结束。
可以用IsBackground来查看该线程是什么类型的线程。
线程异常捕获
public static void Main()
{
try
{
new Thread (Go).Start();
}
catch (Exception ex)
{
// 不能捕获异常
Console.WriteLine ("Exception!");
}
}
static void Go() { throw null; } //抛出 Null异常
此时并不能在Main方法里捕获线程Go方法的异常,如果是Thread自身的异常可以捕获。
正确捕获方式:
public static void Main()
{
new Thread (Go).Start();
}
static void Go()
{
try
{
// ...
throw null; // 这个异常会被下面捕获
// ...
}
catch (Exception ex)
{
// ...
}
}
线程池
当创建一个线程时,就会消耗几百毫秒cpu,创建一些新的私有局部变量栈。每个线程还消耗(默认)约1 MB的内存。线程池通过共享和回收线程,允许在不影响性能的情况下启用多线程。
每个.NET程序都有一个线程池,线程池维护着一定数量的工作线程,这些线程等待着执行分配下来的任务。
线程池线程注意点:
1 线程池的线程不能设置名字(导致线程调试困难)。
2 线程池的线程都是background线程
3 阻塞一个线程池的线程,会导致延迟。
4 可以随意设置线程池的优先级,在回到线程池时改线程就会被重置。
通过Thread.CurrentThread.IsThreadPoolThread.可以查看该线程是否是线程池的线程。
使用线程池创建线程的方法:
Task ThreadPool.QueueUserWorkItem Asynchronous delegates BackgroundWorkerTPL
Framework4.0下可以使用Task来创建线程池线程。调用Task.Factory.StartNew(),传递一个委托
Task.Factory.StartNew
static void Main()
{
Task.Factory.StartNew (Go);
}
static void Go()
{
Console.WriteLine ("Hello from the thread pool!");
}
Task.Factory.StartNew 返回一个Task对象。可以调用该Task对象的Wait来等待该线程结束,调用Wait时会阻塞调用者的线程。
Task构造函数 给Task构造函数传递Action委托,或对应的方法,调用start方法,启动任务
static void Main()
{
Task t=new Task(Go);
t.Start();
}
static void Go()
{
Console.WriteLine ("Hello from the thread pool!");
}










