一,1.默认程序只有一个主线程 代码执行也是默认在主线程执行
如果主线程遇到了 繁重的任务 可以开辟分线程来执行任务 从而不影响主线程的执行
2.C# 到5.0 之前一共有4种创建线程的方式:(
1,,没有参数的调用
(1)1.Thread 自己创建的独立的线程, 优先级高,需要使用者自己管理。
//创建分线程 要执行的任务(委托) 调用 函数方法
ThreadStart childref = new ThreadStart(ProgramMothod);//没有参数的调用 ThreadStart
//创建分线程实例对象 使用委托
Thread childThread = new Thread(childref); // Thread 系统默认好的定义委托
childThread.Name = "分线程1";
//执行分线程
childThread.Start();
public static void ProgramMothod()
{
Console.WriteLine("繁重的任务1");
//
Console.WriteLine(Thread.CurrentThread.Name);
}
(2)//创建线程2 箭头函数 直接使用 里面的方法
Thread thread2 = new Thread(() => {
Console.WriteLine("繁重的任务2");
});
thread2.Start();
(3)
//创建线程3 线程休眠
Thread thread3 = new Thread(() =>
{
Console.WriteLine("繁重的任务3");
//线程休眠 单位毫秒
Thread.Sleep(2000); //让主线程休眠 ()Sleep方法写在哪个线程中 就让哪个线程休眠
Console.WriteLine("繁重的任务33");
});
thread3.Start();
(4)//手动销毁线程
thread4.Abort();
2,
(1),//线程执行 有一个参数的委托 1
ParameterizedThreadStart parameterizedThreadStart = new ParameterizedThreadStart(ProgramMothod2);
Thread thread5 = new Thread(parameterizedThreadStart);
//委托的方法 实际参数 是.Start的重载
thread5.Start(300);
public static void ProgramMothod2(object a)
{
Console.WriteLine("繁重的任务5{0}", a);
}
(2),
//线程执行 有一个参数的委托2
Thread thread6 = new Thread(e => {
Console.WriteLine("繁重的任务5{0}", e);
});
thread6.Start(400);
3,线程阻塞 t.Join()
t.Start();
t.Join();//主线程阻塞 不能执行
t1.Start();
)
二,线程抢占
如果两个线程同时对某个资源进行同时访问(同样的方法 不同的名字);
//开启分线程执行go方法
Thread thread = new Thread(Go);
thread.Name = "分线程1";
Thread thread1 = new Thread(Go);
thread1.Name = "分线程2";
thread1.Start();
thread.Start();
就可能出现 线程抢占
解决方法:lock线程锁 如果某个线程进入方法内时 会锁定方法
直到当前线程执行完毕此方法时 ,后续的线程才能进入方法执行代码
static readonly object locker = new object(); //线程锁对象
static void Go()
{
//(标识对象)
lock (locker)
{
Console.WriteLine(Thread.CurrentThread.Name);
}
}
三,线程池
ThreadPool 线程池
线程和线程池都是进行多线程操作的方式,
线程池是用来保存线程的一个容器,
在程序创建线程来执行任务的时候线程池才会初始化一个线程,
线程在执行完毕之后并不会被销毁,
而是被挂起等待下一个任务的到来被激活执行任务,
当线程池里的线程不够用的时候会新实例化一个线程,
来执行,线程池里的线程会被反复利用。
//ThreadPool 使用线程池 操作线程 (和主线程用法相同)
WaitCallback waitCallback = new WaitCallback(ProgramMothod);
//在分线程中执行方法
ThreadPool.QueueUserWorkItem(waitCallback);
public static void ProgramMothod(object a)
{
Console.WriteLine("dosomething0");
}
//可以直接使用箭头函数 更加简单
ThreadPool.QueueUserWorkItem(e => {
Console.WriteLine("dosomething2");
});
2.如何阻塞主线程 ManualResetEvent
(1)ManualResetEvent mreset = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(e =>
{
Thread.Sleep(2000);
Console.WriteLine("dosomething3");
mreset.Set();
});
(2)//阻塞主线程 等待分线程完成后 执行mreset.Set()后执行后续代码
mreset.WaitOne();