多執行緒應用程式
一、執行緒的基本觀念
1、虛擬的執行單元
2、可以讓程式同時進行多項工作
3、減少系統資源的浪費
4、共用資源的鎖定(Synchronization)
一般在應用程式開啟時,執行環境會自動建立一個執行緒執行程式中的功能,稱之為主執行緒(Main thread)。
每一個程式中的執行緒都是一個虛擬的執行單元,建立之後就會在程式的背景執行交付的工作。
優點
像是程式在開啟網路資源或是開啟資料連結的時候都會有一些等待的時間,多執行最大的好處利用這一些空閒時間執行其它的工作,增加系統資源的使用效率。
缺點
把程式變複雜,不容易除錯
多執行緒應用程式中需要處理共用資源鎖定(synchronization),以及避免程式死結(deadlock)
==========================
二、建立沒有回傳值、沒有參數列的執行緒
1、System.Threading命名空間
2、沒有回傳值、沒有參數列
3、建立執行緒步驟
a、建立執行緒所要呼叫的方法
b、將方式記錄在ThreadStart Delegate實體
c、建立Thread物件實體,傳入ThreadStart Delegate
d、呼叫Thread物件的Start方法,啟動執行緒
Imports System.Threading
Module Module1
Sub Main()
Console.WriteLine("MainThread:Application Start.")
Dim ts As New ThreadStart(AddressOf Work)
Dim worker As Thread = New Thread(ts)
'當背景程式時,主程式執行完,背景程式如未執行完,會直接結束,不會有結果產生
'worker.IsBackground = True
worker.Start()
Console.WriteLine("MainThread:Application End.")
End Sub
Private Sub Work()
'Thread.Sleep(1000)
Console.WriteLine("Thread{0}:" & DateTime.Now.ToLongTimeString())
End Sub
End Module
==========================
三、Thread物件常用成員
1、常用屬性
Name:取得或設定執行緒名稱
Priority:取得或設定執行緒的優先權
ThreadState:取得目前的執行緒狀態
2、常用方法
Join:將執行緒插入目前工作中
Thread.Sleep靜態方法:中止執行緒一段時間再執行
==========================
四、執行緒的生命週期
程式中建立的執行緒,實際由OS的環境執行。
一般機器只有一個CPU,因此雖可以建立多個執行緒,但不能同時執行,由系統排程之後決定先後執行順序,一般由優先權高的執行緒會先被執行。
Windows OS具有分時多工特性,因此執行緒管理較為簡單,當程式呼叫Thread物件方法就可以改變執行緒狀態。
下面是執行生命週期主要的狀態
1、Unstarted:當Thread物件被建立,但是並未進入執行狀態時,即為Unstarted狀態。
2、Running:
a、當Thread物件的start方法之後,執行緒被執行時,就進入Running狀態。
b、當Thread由WaitSleepJoin狀態或是呼叫ResetAbort方法恢復執行時,就進入Running狀態。
3、WaitSleepJoin:當程式呼叫Thread物件的Join方法、Sleep靜態方法或是Monitor.Wait方法時,都會進入WaitSleepJoin狀態,必須等到暫停的原因解除後,才會恢復執行。
4、AbortRequested:當程式呼叫Thread物件的Abort方法,執行緒就會進入AbortRequested狀態。如果沒有呼叫ResetAbort方法,則執行緒就會停止執行(Abort)。
=>執行緒的生命週期狀態,可以透過Thread物件的ThreadState屬性來取得。
=>通常執行緒狀態只與偵錯有關,不適宜使用來同步處理執行緒的活動。
==========================
五、ParameterizedThreadStart Delegate
1、ThreadStart無法代入資料到執行緒執行
改用ParameterizedThreadStart Delegate
=>.NET Framework 2.0中,增加ParameterizedThreadStart Delegate定義
2、規格
(1)沒有回傳值
(2)接收Object型別參數
3、呼叫Thread物件的Start方法時代入參數執行
Imports System.Threading
Module Module1
Private Sub Work(ByVal name As Object)
Console.WriteLine("Work with Parameter:" + name)
End Sub
Sub Main()
Dim doSomething As New ParameterizedThreadStart(AddressOf Work)
Dim worker As Thread = New Thread(doSomething)
worker.Start("John")
End Sub
End Module
==========================
六、中止執行緒執行
1、呼叫Thread物件的Abort方法
a、觸發ThreadAbortException
b、可能危及應用程式定義域中(AppDomain)的其它工作
=>當Abort方法被呼叫時,執行環境會產生ThreadAbortException,除非使用Thread.ResetAbort方法解除Abort狀態,不要執行緒會中止執行
2、建立CriticalRegion
a、使用BeginCriticalRegion及EndCriticalRegion建立關鍵區域
b、避免執行緒停止時導致的不穩定情況發生
=>.NET Framework2.0的執行緒架構中才有
Imports System.Threading
Module P12_2_StoppingThreads
Sub AbortThisThread()
Thread.BeginCriticalRegion()
Console.WriteLine("BeginCriticalRegion")
For i As Integer = 0 To 1000
Console.Write("O")
Next
Console.WriteLine("EndCriticalRegion")
Thread.EndCriticalRegion()
For i As Integer = 0 To 1000
Console.Write("1")
Next
End Sub
Sub main()
Dim newThread As New Thread(New ThreadStart(AddressOf AbortThisThread))
newThread.Start()
Thread.Sleep(1)
Console.WriteLine("abort")
newThread.Abort()
Console.WriteLine("end")
End Sub
End Module
==========================
七、執行緒執行環境(Execution Context)
1、當執行緒被建立時,預設會套用既有執行緒背景環境設定
a、安全性資訊
b、區域語系資訊
c、交易環境資訊
=>當程式建立新執行緒時,有執行緒的Execution Context的設定,像是安全性資訊、區域語系資訊及交易環境的資訊,都會傳遞到新執行緒中套用
2、ExecutionContext物件類別
a、常用方法
(1)SuppressFlow(static method):呼叫此方法可暫停將執行環境的設定傳遞給新的執行緒使用
(2)RestoreFlow(static method):呼叫此方法可恢復繼續執行環境的設定傳遞
(3)Capture(static method):複製目前執行緒的執行環境
(4)Run(static method):可以將程式執行在指定的執行環境中
(5)Undo:呼叫此方法可恢復繼續執行環境的設定傳遞
==========================
八、ThreadPool
1、更有效率的建立執行緒方式
a、系統會自動根據處理器的狀況做最佳化
b、可快速取得多個背景執行緒
=>許多應用程式建立的執行緒把很多時間花費在休眠狀態,等待事件發生;也有的執者進入休眠狀態後只負責定時甦醒,來輪詢變更更新狀態的資訊。
=>ThreadPool可將執行完的執行緒先暫存在集區中,下次程式需要執行緒執行工作時,就可以直接從集區中重覆使用執行緒,節省建立新執行緒所需要消眊的系統資源。
2、不適合情境
a、需要為個別執行緒設定優先權
b、需要為個別執行緒建立identity,讓後緒程式可以使用
c、執行長時間工作
d、用於single-threaded apartment應用程式環境中
=>因執行緒是由集區取出來使用的,因此程式對於該執行緒無法做太多設定,因而不適用在這些狀況
Module Module1
Sub Work(ByVal o As Object)
Console.WriteLine("Work with Parameter:")
End Sub
Sub Main()
Dim WCB As New WaitCallback(AddressOf Work)
If System.Threading.ThreadPool.QueueUserWorkItem(WCB) Then
Console.WriteLine("OK")
End If
End Sub
End Module
==========================
九、Timer物件類別
1、來源
a、System.Form.Form
b、System.threading=>CallBack,會以另一各Thread執行
c、System.Timers=> 事件,會以另一各Thread執行
2、用於定期觸發某特定方法執行
a、Threading.TimerCallback delegate
b、Change方法:用於調整觸發方法的間隔
c、Dispose方法:釋放Timer物件執行時所參考的外部資源
=>Timer可定間隔一段時間觸發某方法,透過Timer觸發方法參考必須要先記錄到TimerCallback Delegate物件之後,再傳到Timer物件中執行
Imports System.Threading
Module Module1
Sub Main()
Dim T1 As New Threading.Timer(New TimerCallback(AddressOf Time), Nothing, 0, 2000)
Console.Read()
End Sub
Sub Time(ByVal o As Object)
Console.WriteLine("Time:" & Date.Now)
End Sub
End Module