進程會等待所有的前台線程完成后再結束本工作;但是如果只剩下后台線程,則會直接結束本工作,不會等待后台線程完成后再結束本工作。
1 new Thread創建的線程
默認情況下使用new Thread()方法創建的線程為前台線程,可以通過手動設置IsBackground屬性來創建一個后台線程;
默認前台線程示例:
#region Thread前后台線程測試 public static void BackGroundTest() { var thread1=new Thread(() => { while (true) { Thread.Sleep(1000); Console.WriteLine(string.Format("thread id :{0} is background:{1}",Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.IsBackground)); } }); // new Thread創建的線程默認為前台線程,會一直運行直到結束 thread1.Start(); } #endregion
測試代碼如下:
static void Main(string[] args) { ThreadTest.BackGroundTest(); Console.WriteLine(string.Format("Main thread id :{0} is background:{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground)); Console.WriteLine("Main Ok"); }
運行結果:
把線程修改為后台線程測試,后台線程代碼如下:
這時候,再重新運行測試代碼,會發現,Main方法運行完后程序后立即退出結束,因為這時候只有一個前台線程即Main方法,當Main方法執行完后,會立即結束所有的后台線程的執行;
2 線程池
C#線程池中的工作線程默認都是后台線程,這意味着當所有的前台線程完成后,所有的后台線程將停止工作;但是可以通過設置修改為前台線程
Thread.CurrentThread.IsBackground = false;
public static void ThreadPooMethod() { ThreadPool.QueueUserWorkItem((p) =>{ while (true) { Thread.Sleep(1000); Console.WriteLine(string.Format("thread id :{0} is background:{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground)); } }); }
主線程測試代碼如下:
static void Main(string[] args) { ThreadPoolTest.ThreadPooMethod(); Console.WriteLine(string.Format("Main thread id :{0} is background:{1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground)); Thread.Sleep(3 * 1000); Console.WriteLine("Main Ok"); }
程序的運行結果是:線程池里的ThreadPooMethod運行了3秒鍾后,程序會結束運行,因為作為唯一前台線程的主線程只會運3秒,Main方法運行結束后線程池里的工作線程會停止運行;
3 Task
對於使用任務Task,一般來說是使用線程池作為后台線程;
public static void BackGroundTest() { var task1=Task.Factory.StartNew(() => { while (true) { Thread.Sleep(1000); Console.WriteLine(string.Format("thread id :{0} is background:{1},is ThreadPool :{2}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground,Thread.CurrentThread.IsThreadPoolThread)); } } ); }
由於默認在線程池里作為后台線程運行,所以當所有前台線程運行完后,該工作線程也會立即結束
可以使用Thread.CurrentThread.IsBackground = false;改為前台線程
這時運行結果如下:
程序會一直運行下去。