c#笔记番外篇同步异步并行串行多线程(以及lambda 表达式)

张开发
2026/4/13 15:37:15 15 分钟阅读

分享文章

c#笔记番外篇同步异步并行串行多线程(以及lambda 表达式)
学习目标:算是一个一直以来的疑惑点而且ltm老师的视频了没有说这个,只能四处找资料;先确定一个答案:就是异步和多线程是两种东西,异步可以在单线程里异步也可以在多线程里异步;同步异步是等不等的问题;比如煮饭和炒菜两件事,同步就是先煮饭等着饭煮好了再做菜;异步就是先淘米上锅煮饭然后在等饭煮好的这段时间里顺便去做菜,在你做菜的这段时间不管饭煮没煮好都会先等你把菜做好;饭煮好了菜没做完你就继续做菜;多线程就是多来一个人,这时候可以一个人做菜一个人煮饭;一、学习前置:1、lambda 表达式这个看另外一篇3.调试在打断点调试多线程的时候在vs里可以打开:调试-窗口-线程;就可以看到当前打断点的这一句是哪个线程一、多线程1.1、进程和线程1.1.1进程一个程序打开就是一个进程;一个进程在一开始的时候执行的第一个线程就是主线程;一个进程可以有多个线程;(线程执行是主线程先执行然后再启动其他线程);1.1.2线程线程是进程内部的执行单元,一个进程至少有一个主线程。线程是程序里做事的最小执行单元,就相当于工厂里的工人,进程就是一个工厂里面可以有很多个工人;或者是是线程就是一条流水线;1.2为什么要有多线程大量任务要同时执行节省时间,你觉得这个方法做起来耗时间就开一个线程让这个方法去别的流水线做事;在winform里就是不卡ui界面,比如要等待读取一个大文件或者通信耗时操作,如果只有一个ui线程在事情没有做完之前界面会卡死没办法操作;1.3 ThreadThread是 .NET 中最底层的线程控制类,直接对应操作系统的内核线程。创建多个Thread就是最简单的多线程;1.3.1声明创建调用无参方法;(会发现线程的调用流程和创建和委托非常像,都是把一个方法给别人去调用;Thread的构造函数接受的就是一个委托,有兴趣可以了解一下)static async Task Main(string[] args) { Stopwatch sw = new Stopwatch();//计时类 sw.Start(); Thread t = new Thread(TestFunc);//创建线程 t.Start();//启动方法 t.Join();//等待方法完成 Console.WriteLine(sw.ElapsedMilliseconds.ToString()+"ms...."); } static void TestFunc() { for (int x = 0; x 5; x++) { Thread.Sleep(200); Console.WriteLine(x+"work...."); } }带参数的方法class Program { static void Main() { // 方式1:使用 ParameterizedThreadStart;使用这种的时候方法声明有要求 Thread t1 = new Thread(DoWorkWithParam); t1.Start("Hello World"); // 方式2:使用匿名函数捕获变量(更灵活) Thread t2 = new Thread(() = { TestFunc1(1, 2); }); //Thread t2 = new Thread(() = TestFunc1(1, 2));//这个是lambda一行代码的简写 t2.Start(); } static void DoWorkWithParam(object? obj)//参数只能是object类型,在方法里再强制转换 { string msg = obj as string ?? string.Empty; Console.WriteLine($"收到参数: {msg}"); } static void TestFunc1(int x,int y) { Console.WriteLine(msg); } }1.3.2 线程名. Start()开始启动线程,创建线程要靠这个方法来启动线程;多个线程时谁先Start就谁先运行;运行之后就是随机的了;Thread t = new Thread(TestFunc);//创建线程 t.Start();//启动方法1.3.3 线程名.Join()等待等待线程的完成,必须线程的任务完成了程序才会往下执行,如果线程的任务是个while循环的话用了join程序就永远不会执行下面的了,而且Join()是同步阻塞方法。如果在 UI 线程(主线程)上调用t.Join(),UI 线程会被完全卡住;join支持堵塞时间比如堵塞100ms就是:join(100)Thread t = new Thread(TestFunc);//创建线程 Thread t2 = new Thread(() = { TestFunc1(1, 2); }); //Thread t2 = new Thread(() = TestFunc1(1, 2)); t.Start();//启动方法 t.Join();//等待方法完成 Console.WriteLine(sw.ElapsedMilliseconds.ToString()+"ms....");1.3.4 Thread.sleep()休息Thread.Sleep 就是让「当前正在执行这段代码的线程」原地休息。它只认执行代码的线程,不认你是哪个方法写的。也就是哪个线程里调用就会休息哪个线程;(在winiform编程里线程里的while最好不要用true而是用个标志位,在关闭窗口或者别的时候要关闭线程的时候就标志位false就可以关闭线程,因为在线程里的事做完之后线程会自动关闭)这种情况因为Thread.Sleep(100);放在了 this.Invoke里被一起送去了ui线程 所以sleep的是ui线程而不是线程t1;这种时候ui线程会卡顿 t1 = new Thread(() = { int x = 0; while (true) { this.Invoke(() = { textBox1.Text = x.ToString(); Thread.Sleep(100); }); x++; } }); t1.Start(); ////////////////////////////////////////////////////////////// 这样才是t1休息 t1 = new Thread(() = { int x = 0; while (true) { this.Invoke(() = { textBox1.Text = x.ToString(); }); x++; Thread.Sleep(100); } }); t1.Start();1.3.5 Thread的停止1线程名.abort():不管线程在干嘛,直接强制结束;这种方法是非常旧的停止方法现在微软以及停止使用了,老版本还可以用;private void button1_Click(object sender, EventArgs e) { t1 = new Thread(() = { thread.sleep(50000); }); t1.Start(); } private void button2_Click(object sender, EventAr

更多文章