1. 程式人生 > 其它 >多執行緒啟動停止暫停繼續

多執行緒啟動停止暫停繼續

前言

初學者學習程式設計時,很容易因為多執行緒出現各種問題,導致不敢使用多執行緒。但是多執行緒技術在做開發中,是不可忽視的一個技術,基本上我們實際應用中,每個專案都會使用多執行緒,所以多執行緒技術必須掌握。

為什麼要用多執行緒

隨著工業的進步,現在的筆記本、桌上型電腦大都是雙核的,4核、8核甚至16核,也很常見,如果是單執行緒的程式,那麼在雙核CPU上就浪費了50%,在4核CPU上就浪費了75%。

單核CPU上所謂的”多執行緒”那是假的多執行緒,同一時間處理器只會處理一段邏輯,只不過執行緒之間切換得比較快,看著像多個執行緒”同時”執行罷了。

多核CPU上的多執行緒才是真正的多執行緒,它能讓你的多段邏輯同時工作,多執行緒,可以真正發揮出多核CPU的優勢來,達到充分利用CPU的目的。

如果你做專案不使用多執行緒,不僅是技術的問題,也是對電腦資源的極大浪費,就像你買了一輛配置非常高的越野車,你僅僅只用它來日常代步一樣。

為什麼不敢用多執行緒

之前跟一些學員溝通時發現,很多學員之所以不敢使用多執行緒,是因為之前出過問題,有種“一朝被蛇咬,十年怕井繩”的感覺。

為什麼多執行緒容易出問題,有個主要的原因在於多執行緒充滿著“未知性”,有的人使用時,發現程式碼並沒有按照預想的流程在走,這其實是正常的。

我們必須要明確一點,多執行緒確實是“不可控的”,有某種意義上來說,多執行緒是靠CPU排程來執行的,並非人為去控制。

我們所謂的控制多執行緒,僅僅是.NET框架開放了一些介面給開發者(需要相關程式碼加VX:xiketang777),這樣可以相對性地間接控制多執行緒的啟動停止暫停繼續。

執行緒的啟動停止

執行緒的啟動停止,從.Net Framework 4.5開始,Task提供了一個叫CancellationTokenSource的物件,可以使用它來對多執行緒的啟停進行控制。

首先,我們做一個執行緒任務,這個任務很簡單,只是不斷操作某個變數,每0.1秒加1,到一定值之後,重置為0,然後將這個值顯示在介面上,介面如下所示:

所以任務方法如下:

我們可以看到在方法裡呼叫了一個cts物件,這個物件就是CancellationTokenSource的物件,因此我們需要建立一個CancellationTokenSource物件cts:

然後在啟動執行緒按鈕的事件裡,編寫程式碼如下:

停止執行緒按鈕的事件裡,只需要呼叫cts的Cancel方法即可:

其實,說白了,就是通過cts來控制cts的IsCancellationRequested屬性,進而實現多執行緒的控制。

執行緒的暫停繼續

多執行緒的暫停繼續,.NET為我們提供了另外一個物件——ManualResetEvent,這個物件會有一個值,這個值是布林型別,就像一個門閘一樣,True是開啟門閘,False是關閉門閘(需要多執行緒資料加VX:xiketang777),所以想要暫停多執行緒就呼叫這個物件的Reset方法,想要繼續多執行緒就呼叫這個物件的Set方法,使用非常簡單。

首先我們建立一下這個物件,可以通過構造方法,給這個物件賦初始值,我這裡為True,這樣就能直接執行,不會阻塞。

但是如果希望這個物件與多執行緒有所聯絡,必須要在多執行緒的方法裡體現這個物件的作用,這個是呼叫這個物件的WaitOne方法,表示在呼叫的地方阻塞住,通過判斷True或者False來決定是否繼續執行(需要多執行緒資料加VX:xiketang777),就像大家開車過高速收費站一樣,即使現在普遍採用ETC了,在入口也需要減速,有一個ETC識別的過程,識別成功才會抬杆,識別不出來,杆子是不會自動抬起的,這個是一樣的道理。

所以執行緒執行程式碼如下:

對比一下,其實就是加了一個manual.WaitOne()。

執行緒暫停程式碼:

執行緒繼續程式碼:

AutoResetEvent

AutoResetEvent和ManualResetEvent的用法非常相似,區別在於一個是手動,一個是自動,AutoResetEvent會在置位之後自動復位,這樣體現在多執行緒裡,就是會只執行一次,就像大家進小區一樣,如果有10輛車在排隊,這時候如果自動模式,每次只能進一輛車,如果是手動模式,可以由保安控制門閘開啟,等10輛車都進去之後,再由保安將門閘關注。