C# 多线程
一、线程开启方式1-Thread类
(1) 传递参数 1 start()中传递参数:
static void Download(object filename)
{
Console.WriteLine(filename+"下载开始" +Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
Console.WriteLine("下载结束");
}
static void Main(string[] args)
{
Thread t = new Thread(Download);
t.Start("XXX.txt");
Console.WriteLine("Main");
Console.ReadKey();
}
(2) 传递参数 2 调用类中的方法
static void Main(string[] args)
{
MyThread myThread = new MyThread("XXX.txt", "http://www.baidu.com");
Thread thread =new Thread(myThread.DownLoad);
thread.Start();
Console.WriteLine("Main");
Console.ReadKey();
}
public class MyThread
{
private string filename;
private string filepath;
public MyThread(string filename,string filepath)
{
this.filename = filename;
this.filepath = filepath;
}
public void DownLoad()
{
Console.WriteLine(filename + filepath + "下载开始");
Thread.Sleep(2000);
Console.WriteLine("下载结束");
}
}
(3) 后台线程、前台线程、线程的状态
- 判断一个应用程序是否结束需要判断前台线程是否都运行结束。当多个前台线程在运行时,如果main方法运行结束了,只要有一个前台线程在运行,应用程序的进程任然是运行的。
用Thread创建的是前台线程,线程池中的线程总是后台线程。当所有前台线程运行完毕,后台线程也会终止。
// 如何把线程设置为后台线程
thread.IsBackground = true;
- 使用Abort()方法可以停止线程,调用这个方法会抛出异常,可以根据try…catch这个异常在线程结束前做一些清理工作。
- 如果需要等待线程的结束,调用Join()方法,即停止当前线程,把线程join进来,执行完后执行后续代码。
- 线程的基本状态有就绪、阻塞、运行三种。
二、线程开启方式2-线程池
- 线程池的线程调用的方法必须有一个参数
- 线程池中的线程都是后台线程
- 线程池中的线程不能改为前台线程
static void ThreadMethod(object state)
{
Console.WriteLine("线程开始 id"+Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
Console.WriteLine("线程结束");
}
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(ThreadMethod);
ThreadPool.QueueUserWorkItem(ThreadMethod);
ThreadPool.QueueUserWorkItem(ThreadMethod);
ThreadPool.QueueUserWorkItem(ThreadMethod);
ThreadPool.QueueUserWorkItem(ThreadMethod);
Console.WriteLine("Main");
Console.ReadKey();
}
三、线程开启方式3-任务
// 任务创建的方法-创建一个Task实例
Task t = new Task(ThreadMethod);
t.Start();
// 任务创建的方法-实例化TaskFactory类
TaskFactory tf = new TaskFactory();
tf.StartNew(ThreadMethod);
// 任务创建的方法-Factory属性
Task tf = Task.Factory.StartNew(ThreadMethod);
四、线程问题-争用条件和死锁
争用条件:当多个线程同时访问同一数据时,每个线程都尝试操作改数据,从而导致数据被破坏,这种现象称为争用条件。
解决:加锁lock,只能锁定引用类型,在同一时刻只有一个线程在对同一个数据进行访问。
死锁:如果执行操作需要两个资源,当两个线程分别锁定两个资源,都在等待另一个线程执行完毕释放资源,此时就会造成死锁。
解决死锁:设定锁定顺序(不知道另一种方法可不可以:在等待一段时间后同时释放锁定的资源)