1、使用線程的情況
① 程式需要執行和兩個和多個任務
② 程式要等待某事件的發生:例如使用者輸入、檔案操作、網路操作和搜尋
③ 背景程式
2、多線程的並發執行
如果有多個線程在執行,單CPU只有一個,到底執行的哪個?
① 如果一個線程連續佔用CPU資源時間過長,其它的資源得不到執行,則系統會強制的切換執行其它線程。(強制剝奪)
② 如果一個線程沒事可做、CPU可執行其它線程。(主動放棄)
③ 這是由作業系統的調度機制決定的,不同的作業系統調度機制不一樣。一般無法精確的預料多線程的執行順序,在程式設計的時候應特別注意。
3、建立並啟動線程
ThreadStart 線程啟動委託名=new ThreadStart(方法名);
Thread 線程執行個體名=new Thread(線程啟動委託名);
線程執行個體名.Start();
4、終止線程
① 線程執行個體名.Abort():用此方法的後果是不可恢複的終止線程。
② 線程執行個體名.Interrupt():中斷後可恢複。
5、休眠線程
① 線程執行個體名.Sleep():
當線程Sleep時,系統就立即退出執行隊列一段時間,當睡眠結束時,系統會產生一個時鐘中斷,從而使線程回到執行隊列中,從而恢複線程的執行。
6、掛起/恢複線程
① 線程執行個體名.Suspend():
掛起與線程休眠不同,線程的掛起不會使線程立即停止執行,直到線程到達安全點之後它才可以將該線程掛起,如果線程尚未啟動或已經停止,則它將不能掛起。
② 線程執行個體名.Resume():恢複將使一個線程跳出掛起狀態並使該線程繼續執行。
一個線程不能對另一個線程調用Sleep() ,但是一個線程可以對另一個線程調用Suspend()。
還可以使用許多其它的方式來阻塞線程。例如,可以通過調用 Thread.Join 使一個線程等待另一個線程(子線程)停止。使用Monitor.Wait使一個線程等待訪問一個同步對象。
7、序列化線程
① 線程執行個體名.jion():
例如在主線程中插入t.jion(),主線程執行到這條語句後,主線程(當前線程)立即進入阻塞狀態.直到t運行完後阻塞狀態才解除。
相當於把t的任務插入或串聯到主線程中,把兩條線索串聯成一條線索。
8、線程的鎖定機制
線程的鎖定機制可以保證每次只有一個線程可以訪問共用資源。
使用關鍵字lock:
① ock語句的文法
lock(對象引用)語句塊;
② lock語句的功能
當對象被lock 鎖定時,訪問該線程的其它線程會進入等待的狀態。
③ 對象鎖機制保證了對象訪問的完整性:只有一個線程完成操作後,其它的線程才能進行操作。
④ 一般情況下,當一個線程寫某個變數,而同時可能有其它的線程讀或寫這個變數時,為了保持資料的一致性應該使用鎖定機制。
⑤ 線程的安全性
執行緒安全性就是保護的類的成員和代碼的安全,從而使他們不會同時被幾個線程中斷,使用鎖定機制。
⑥ 多線程公用一個對象時,就不應該使用lock關鍵字了,這裡Monitor,Monitor提供了使線程共用資源的方案。
Monitor類可以鎖定一個對象,一個線程只有得到這把鎖才可以對該對象進行操作。
如:
Monitor.Enter(obj);
Monitor.Exit(obj);
⑦ 臨界區和鎖
當談論多線程應用程式的時候,首先應該想到的就是並發性問題。儘管這對於同時執行多個任務的程式是很有用的,但通常都是危險的。
為瞭解決這個問題,在C#中提出了臨界區和鎖的概念。在程式設計中,臨界區是一塊在任何時候只能有一個進程進入的地區。
在C#中通過語句lock來聲明臨界區。lock聲明後面的代碼,不管是以行還是一塊代碼,在同一時間最多隻能有一個進程執行。
9、線程的優先順序具有不可靠性,就是說不能用優先順序來控制線程的執行順序。
10、後台線程
① 什麼是後台線程?
比起應用程式的主圖形化使用者介面(GUI)線程來說,這些線程以較低的優先權在不同的過程中運行著。對於不能立即執行結束,又不想一直等待的任務,後台線程能很好的勝任。
在C#中,把線程對象的IsBackground屬性設為true,該線程即為後台線程。
後台線程跟前台線程只有一個區別,那就是後台線程不妨礙程式的終止。一旦一個進程所有的前台線程都終止後,CLR將通過調用任意一個存活中的後台進程的Abort()方法來徹底終止進程。
注意:後台線程不能直接操作所在進程之外的資料引用。
② 怎樣與後台線程通訊?
運用MethodInvoker委派實體。
也可在初始化(建構函式)中加入下面一句即可實現通訊:
Control.CheckForIllegalCrossThreadCalls = False;
要使用MethodInvoker委派,需要三個條件:
a、一個建立委派的後台線程
Thread thread=new Thread(new ThreadStart(Run)); thread.IsBackground=true;//把Thread設為後台線程 thread.Start();
b、一個用作後台線程與前台可視化單元的介面的類級方法
public void Run(){ int count=0; try { //建立一個委託,UpdateLabel是該委託所託管的代碼,必須是聲明為void 且不接受任何參數的任何方法。 MethodInvoker mi=new MethodInvoker(this.UpdateLabel); while(true) { count++; //this.Invoke(mi);//同步執行委託 this.BeginInvoke(mi);//非同步執行委託 Thread.Sleep(500); } } catch(ThreadInterruptedException e) { Console.WriteLine("Interruption Exception in Thread:{0}",e); } catch(Exception ex) { Console.WriteLine("Exception in Thread:{0}",ex); }}
c、一個應用程式中可以更新的可視化單元
public void UpdateLabel(){ label1.Text=count.ToString();}
參考:http://cfg1014.blog.163.com/blog/static/663439920096991337523/?hasChannelAdminPriv=true