一.Thread的使用方式
1.不帶參數
(1)使用lambda
public static void fun1() { Console.WriteLine($"Main ThreadId:{Thread.CurrentThread.ManagedThreadId}"); new Thread(new ThreadStart(() => { Console.WriteLine($"Thread ThreadId:{Thread.CurrentThread.ManagedThreadId}"); })).Start(); }
(2)使用方法
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類型參數)
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.等待線程執行
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.示例
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.結束進程方式關聯
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