C#Thread学习
一.Thread的使用方式
1.不带参数
(1)使用lambda
1 2 3 4 5 6 7 8 | public static void fun1() { Console.WriteLine($ "Main ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); new Thread( new ThreadStart(() => { Console.WriteLine($ "Thread ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); })).Start(); } |
(2)使用方法
1 2 3 4 5 6 7 8 9 10 | public static void ConsoleString() { Console.WriteLine($ "Thread ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); } public static void fun2() { Console.WriteLine($ "Main ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); new Thread( new ThreadStart(ConsoleString)).Start(); } |
2.带参数(只允许带一个object类型参数)
1 2 3 4 5 6 7 8 | public static void fun3() { Console.WriteLine($ "Main ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); new Thread( new ParameterizedThreadStart(t => { Console.WriteLine($ "{t} Thread ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); })).Start( "haha" ); } |
3.等待线程执行
1 2 3 4 5 6 7 8 9 10 11 12 | public static void fun4() { Console.WriteLine($ "Main start ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); Thread t = new Thread( new ThreadStart(() => { Thread.Sleep(1000); Console.WriteLine($ "Thread ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); })); t.Start(); t.Join(); Console.WriteLine($ "Main end ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); } |
执行结果:
4.结束线程
Abort();
二.IsBackground讲解
thread.IsBackground=true:该线程为后台线程
thread.IsBackground=true:该线程为前台线程,Thread默认为前台线程
1.前台线程和后台线程的区别
Net的公用语言运行时(Common Language Runtime,CLR)能区分两种不同类型的线程:前台线程和后台线程。这两者的区别就是:应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。
原理:只要所有前台线程都终止后,CLR就会对每一个活在的后台线程调用Abort()来彻底终止应用程序
2.使用建议
对于一些在后台运行的线程,当程序结束时这些线程没有必要继续运行了,那么这些线程就应该设置为后台线程。比如一个程序启动了一个进行大量运算的线程,可是只要程序一旦结束,那个线程就失去了继续存在的意义,那么那个线程就该是作为后台线程的。而对于一些服务于用户界面的线程往往是要设置为前台线程的,因为即使程序的主线程结束了,其他的用户界面的线程很可能要继续存在来显示相关的信息,所以不能立即终止它们。这里我只是给出了一些原则,具体到实际的运用往往需要编程者的进一步仔细斟酌。
一般后台线程用于处理时间较短的任务,如在一个Web服务器中可以利用后台线程来处理客户端发过来的请求信息。而前台线程一般用于处理需要长时间等待的任务,如在Web服务器中的监听客户端请求的程序,或是定时对某些系统资源进行扫描的程序。
3.示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public static void fun5() { Thread t1 = new Thread( new ThreadStart(() => { for ( int i = 0; i < 50; i++) { Thread.Sleep(100); Console.WriteLine($ "Thread1 {i} ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); } })); t1.Start(); Thread t2 = new Thread( new ThreadStart(() => { for ( int i = 0; i < 100; i++) { Thread.Sleep(100); Console.WriteLine($ "Thread2 {i} ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); } })); t2.IsBackground = true ; t2.Start(); } |
运行结果:
当t1执行完后,t2也不在执行,说明t1执行完成后,进程结束。
4.结束进程方式关联
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | private void fun() { Thread t1 = new Thread( new ThreadStart(() => { for ( int i = 0; i < 50; i++) { Thread.Sleep(1000); Debug.WriteLine($ "Thread1 {i} ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); } })); t1.Start(); Thread t2 = new Thread( new ThreadStart(() => { for ( int i = 0; i < 100; i++) { Thread.Sleep(1000); Debug.WriteLine($ "Thread2 {i} ThreadId:{Thread.CurrentThread.ManagedThreadId}" ); } })); t2.IsBackground = true ; t2.Start(); } |
(1)winform中:Application.Exit():所有线程都结束后(前台线程都结束后,后台线程自动结束),然后进程结束
执行 Application.Exit()
结果:等待t1执行完后,t2也不在执行,然后结束进程。
(2)Environment.Exit(0):不等待线程结束,直接结束进程
执行 Environment.Exit(0)
结果:直接结束进程,不等待线程。
参考:
https://blog.csdn.net/Fenglele_Fans/article/details/78555895
https://www.cnblogs.com/Again/articles/7085596.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本