.NET:如何讓線程支持超時?


背景

本文是為了回復博客園一個兄弟的問題,主要回答兩個問題:

  1. 如何讓線程支持超時?
  2. 如何讓線程在執行結束后銷毀?

MS 現在不推薦使用低級別的 Thread 編程,而推薦使用 Task,另外我多數情況都是做企業應用,很少需要多線程編程的場景,本文中的知識都是從 《clr via c#》學習而來。

如何讓線程支持超時?

使用 CancellationTokenSource

代碼

 1         private static void TimeoutTest1()
 2         {
 3             var cts = new CancellationTokenSource();
 4 
 5             var thread = new Thread(() =>
 6             {
 7                 Console.WriteLine(String.Format("線程{0}執行中", Thread.CurrentThread.ManagedThreadId));
 8                 Thread.Sleep(10000);
 9                 Console.WriteLine(String.Format("線程{0}執行中", Thread.CurrentThread.ManagedThreadId));
10             });
11 
12             cts.Token.Register(() =>
13             {
14                 thread.Abort();
15             });
16             cts.CancelAfter(1000);
17 
18             thread.Start();
19             thread.Join();
20 
21             Console.WriteLine(String.Format("線程{0}的狀態:{1}", thread.ManagedThreadId, thread.ThreadState));
22         }

輸出

備注

這里采用了 Abort 終止了線程,CancellationTokenSource 也支持其它模式,可以去官方看看文檔。

使用 Join

代碼

 1         private static void TimeoutTest2()
 2         {
 3             var thread = new Thread(() =>
 4             {
 5                 Console.WriteLine(String.Format("線程{0}執行中", Thread.CurrentThread.ManagedThreadId));
 6                 Thread.Sleep(10000);
 7                 Console.WriteLine(String.Format("線程{0}執行中", Thread.CurrentThread.ManagedThreadId));
 8             });
 9 
10             thread.Start();
11             thread.Join(1000);
12             thread.Abort();
13 
14             Console.WriteLine(String.Format("線程{0}的狀態:{1}", thread.ManagedThreadId, thread.ThreadState));
15         }

輸出

基於 Task 的實現

代碼

 1         private static void TimeoutTest3()
 2         {
 3             var cts = new CancellationTokenSource();
 4             var task = new Task(() =>
 5             {
 6                 while (true)
 7                 {
 8                     cts.Token.ThrowIfCancellationRequested();
 9 
10                     Console.WriteLine("xxxxxx");
11                     Thread.Sleep(1000);
12                 }
13             }, cts.Token);
14 
15             task.Start();
16 
17             cts.CancelAfter(5000);
18 
19             Console.ReadLine();
20         }

輸出

如何讓線程在執行結束后銷毀?

線程執行完、遇到未處理異常和被終止后就自動不可用了,如果是垃圾,自然會被 GC 給回收,有一點需要說明的是:線程的未處理異常會導致應用程序的終止,一個線程的異常不會自動冒泡到其它線程。

備注

我學習多線程知識感覺到的一個好處就是:讓我對數據庫並發有了更深刻的認識了,找個機會寫寫線程的樂觀鎖和數據庫的樂觀鎖的比較,思路基本一樣。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM