




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
2024/4/29可視化程序設計主講:周建偉1內容提要進程與線程的概念應用程序域在C#中使用多線程線程同步問題線程同步的基本方法進程與線程的基本概念2024/4/293進程正在執行的程序稱為進程。與進程相關的信息包括:進程標示(進程ID)、文件名、執行的程序和數據,運行時間、在存儲器中的位置、占用的內存容量等。線程將一個進程劃分為若干個獨立的執行流,每一個執行流均稱為一個線程。(1)線程是CPU調度和分配的基本單位。(2)每個進程都有一個主線程。(3)除了主線程以外,還可以給一個進程分配若干個子線程,從而達到多個任務并行執行的目的。進程(超市)食品服裝體育用品文具數據(商品)線程(收銀臺)CPU(收銀員)多線程應用程序域AppDomain把進程的4G空間又做了劃分把一個大屋子進一步隔成多個小屋子從這個意義上,AppDomain是“亞進程”兩個應用程序域占用獨立的數據空間,且不能互相訪問地址不能相同,因為在同一個進程里面代碼空間可以重疊,相當于一個程序啟動多遍線程同一時刻只能在一個應用程序域中運行默認的AppDomain是整個進程空間食品AppDomain(承包區)進程(超市)服裝AppDomain家電AppDomain線程仍直屬進程,它們可以先后運行于不同的AppDomain(收款臺直屬超市收完買服裝的再收買食品的)進程管理(Process類)2024/4/297Process類常用的屬性和方法-----------------------獲取進程實例-------------------GetProcessById方法(靜態方法):通過進程Id創建新的Process組件,并將其與本地計算機上的進程資源關聯。GetProcessById最多只有一個Process實例。GetProcesses方法(靜態方法):獲取本機所有進程GetProcessesByName方法(靜態方法):獲取本機上特定名稱的進程-----------------------獲取及設置優先級---------------BasePriority屬性:獲取進程優先級(只讀)PriorityClass屬性:設置或更改進程優先級進程管理(Process類)2024/4/298---------------------------進程ID及進程名-----------------------Id屬性:獲取關聯進程的唯一標識符ProcessName屬性:獲取該進程的名稱,不包括路徑和擴展名-----------------------------進程其他信息-------------------------------MachineName屬性:獲取關聯進程正在其上運行的計算機名稱MainModule屬性:獲取關聯進程的主模塊Modules屬性:獲取由關聯進程加載的模塊TotalProcessorTime屬性:獲取進程的總的處理器時間StartTime屬性:獲取關聯進程的啟動時間WorkingSet64屬性:為進程分配的物理內存量(字節數)進程管理(Process類)2024/4/299-----------------------進程啟動-------------------------Start方法:啟動進程資源并將其與Process組件關聯StartInfo屬性:獲取或設置要傳遞給啟動進程的文件名以及啟動參數-----------------------進程終止-------------------------Kill方法:強制終止進程CloseMainWindow方法:關閉具有用戶界面的進程Close方法:釋放與此組件關聯的所有資源HasExited屬性:指示關聯進程是否已終止WaitForExit方法:設置等待關聯進程退出的時間,并在該段時間結束前或該進程退出前,阻止當前線程執行。獲取進程信息2024/4/29101、如何獲取進程信息(1)獲取本地計算機的所有進程:
Process[]myProcesses=Process.GetProcesses();(2)獲取本地計算機上指定名稱的進程:
Process[]myProcesses=
Process.GetProcessesByName("進程名稱");注意:(a)進程名稱不帶擴展名。(b)可以是任何一個可執行文件例如:
Process[]myProcesses=Process.GetProcessesByName("WindowApplication1");獲取進程信息2024/4/2911(3)獲取遠程計算機的所有進程:Process[]myProcesses=Process.GetProcesses(remoteMachineName);例如:
Process[]myProcesses=
Process.GetProcesses("");(4)獲取遠程計算機上指定名稱的進程:
Process[]myProcesses=Process.GetProcessesByName("遠程進程名稱",remoteMachineName);啟動和停止進程2024/4/29121.啟動進程:方法1:(1)創建一個Process組件的實例,例如:
ProcessmyProcess=newProcess();(2)設置其對應的StartInfo屬性,指定要運行的應用程序名以及傳遞的參數:
myProcess.StartInfo.FileName="文件名";
process1.StartInfo.Arguments="參數";如果該進程帶有圖形用戶界面,也可以指定圖形用戶界面的打開方式。例如:
myProcess.StartInfo.WindowStyle=ProcessWindowStyle.Normal;(3)調用該實例的Start方法啟動該進程。方法2:
直接調用Process類提供的靜態方法啟動進程。啟動和停止進程2024/4/29132.停止進程通過兩種方法利用Process組件停止進程。(1)如果進程有圖形用戶界面,調用CloseMainWindow方法。(2)如果進程沒有用戶界面,調用進程的Kill方法。不論有沒有圖形用戶界面,如果希望強行讓其退出,在權限允許的情況下,均可以調用Kill方法終止該進程。線程管理(Thread類)2024/4/2914Thread類位于System.Threading命名空間下。Thread類是用于創建和控制線程的,對線程的常用操作有:啟動線程、終止線程、合并線程和讓線程休眠等。Thread類提供的常用屬性IsAlive屬性:獲取一個值,該值指示當前線程的執行狀態。如果此線程已啟動并且尚未正常終止,則為true;否則為falseIsBackground屬性:獲取或設置一個值,該值指示某個線程是否為后臺線程。是后臺線程或即將成為后臺線程,則為true;否則為falsePriority屬性:獲取或設置一個值,該值指示線程的調度優先級線程管理(Thread類)2024/4/2915Thread類提供的常用方法Start方法:啟動線程Join方法:將指定的線程合并到當前線程中,并阻止當前線程執行,直到指定的線程終止或經過了指定的時間為止Sleep方法:將當前線程阻止指定的毫秒數,零(0)表示應掛起此線程以使其他等待線程能夠執行Abort方法:在調用此方法的線程上引發ThreadAbortException,以開始終止此線程的過程。調用此方法通常會終止線程前臺線程和后臺線程2024/4/2916一個線程要么是后臺線程要么是前臺線程。后臺線程與前臺線程類似,區別是后臺線程不會影響進程終止。屬于某個進程的所有前臺線程都終止后,公共語言運行庫就會結束該進程,而且所有屬于該進程的后臺線程也都會立即停止,而不管后臺工作是否完成。利用Thread對象的IsBackground屬性,可以設置或判斷一個線程是后臺線程還是前臺線程。通過將某個線程的IsBackground屬性設置為true,使其變為后臺線程。默認情況下,屬于托管線程池的線程(即其IsThreadPoolThread屬性為true的線程)都是后臺線程,通過創建并啟動新的Thread對象而生成的線程都是前臺線程。線程的基本操作2024/4/29171.啟動線程啟動線程前,首先要創建一個線程。創建無參數線程的一般形式為:
Threadt1=newThread(線程名);創建帶參數線程的一般形式為(傳遞一個Object類型的參數):
Threadt2=newThread(線程名(Objectobj));創建線程實例后,就可以調用Start方法啟動線程了。例如:
t1.Start();//不帶參數
t2.Start(“myClass”);//帶參數注意:調用Start只是告訴系統啟動該線程,但是系統并不一定會立即啟動它。線程的基本操作2024/4/29182.終止線程
兩種方法:事先設置一個布爾字段,在其他線程中通過修改該布爾量的值作為傳遞給該線程是否需要終止的判斷條件,而在該線程中循環判斷該布爾值,以確定是否退出線程,這是結束線程比較好的方法,實際應用中一般使用這種方法。調用Thread類的Abort方法,該方法的最終效果是強行終止線程。線程的基本操作2024/4/29193.暫停線程在多線程應用程序中,有時候并不希望某一個線程繼續執行,而是希望該線程暫停一段時間,這樣,CPU就會將其時間片中剩余的部分讓給另一個線程。調用Thread類的Sleep方法可以實現這個功能。例如:
Thread.Sleep(1000);
這條語句的功能是讓當前線程暫停1000毫秒。注意
Sleep方法是靜態方法,暫停的是該語句所在的線程,而不是其他線程。線程的基本操作2024/4/29204.合并線程Join方法用于把指定的線程合并到當前線程中,從而使其變為一個單個的線程。如果一個線程t1在執行的過程中需要等待另一個線程t2結束后才能繼續執行,可以在t1的代碼塊中調用t2的join方法。例如:
t2.Join();
功能:t1在執行到t2.Join()語句后,就處于暫停狀態,直到t2結束后才會繼續執行。為了避免t1一直等待,可以在調用t2的Join方法的時候指定一個暫停時間,例如:t2.Join(100);在一個線程中操作另一個線程的控件2024/4/2921默認情況下,在Windows應用程序中,.NETFramework不允許在一個線程中直接操作另一個線程中的控件,這是因為訪問Windows窗體控件本質上不是線程安全的。在應用程序中,如果創建某控件的線程之外的其他線程試圖調用該控件,則系統會引發一個InvalidOperationException異常。有兩種辦法可以解決這個問題:(1)使用委托(delegate)操作另一個線程中的控件(2)用BackgroundWorker組件在后臺執行線程在一個線程中操作另一個線程的控件(續)2024/4/2922利用委托調用另一個線程控件(方法1):delegatevoidAppendStringDelegate(stringstr);privatevoidAppendString(stringstr){
if(richTextBox1.InvokeRequired){
AppendStringDelegated=AppendString;richTextBox1.Invoke(d,str);}
else{richTextBox1.Text+=str;}}2024/4/2923利用委托調用另一個線程控件(方法2):privatedelegatevoidAppendStringDelegate(string
str);publicvoidAppendString(stringstr){richTextBox1.BeginInvoke(
newAppendStringDelegate(AddMessageToRichTextBox),
newObject[]{message});}privatevoidAddMessageToRichTextBox(stringmessage){richTextBox1.AppendText(message);}線程的優先級2024/4/2924五個優先級,由高到低分別是:Highest、AboveNormal、
Normal(默認)、BelowNormal和Lowest可以使用下面的方法為其賦予較高的優先級:
Threadt=newThread(MethodName);t.priority=ThreadPriority.AboveNormal;通過設置線程的優先級可以改變線程的執行順序,所設置的優先級僅僅適用于這些線程所屬的進程。注意:當把某線程的優先級設置為Highest時,系統正在運行的其他線程都會終止,所以使用這個優先級別時要特別小心。線程同步2024/4/2925為什么要同步 如果不同步,線程訪問共享資源時可能出錯對象讀取讀取寫入寫入線程的數據訪問線程體是代碼,代碼要訪問數據兩個線程同時要求訪問同一個數據?DataSetds=CreateDataSet();//......dataGridView1.DataSource=ds;DataSetds=CreateDataSet();foreach(DataTabledtinds.Tables{//....}ds.Tables.Add(newDataTable())//....//.....線程同步確保進程內的一個資源不能同時被寫同時寫,結果不可預知可以同時讀,因為數據并不改變寫的時候也不能讀,數據不完整策略:確保寫操作只有一個線程可執行。一個線程寫的時候,其它線程全阻止(不能讀也不能寫)寫完后,允許其它線程訪問。如果下一個訪問的線程也是寫,則又一次阻止除自己外的所有線程沒人寫,不限制。線程同步2024/4/2928解決方法:System.Threading命名空間提供了多個用于同步線程的類這些類包括Mutex、Monitor、Interlocked等。在實際應用中經常使用lock語句完成線程同步。 該語句簡化了編程的復雜性,使程序看起來既清晰又簡潔一種簡單的同步辦法classProgram{staticboolcanRead=true;staticboolcanWrite=true;staticvoidMain(string[]args){Threadread1=newThread(ReadThread);read1.Start();Threadread2=newThread(ReadThread);read2.Start();Threadwrite1=newThread(WriteThread);read1.Start();Threadwrite2=newThread(WriteThread);write2.Start();}
staticpublicvoidWriteThread(){
if(canWrite){
canWrite=false;
canRead=false;//寫數據
}
canWrite=true;
canRead=true;}staticpublicvoidReadThread(){
if(canRead){
canWrite=false;//讀數據
}
canWrite=true;}}問題:非原子操作if(canWrite){canWrite=false//...}moveax,canWritecmpeax,0jleexitmoveax,-1movcanWrite,eax....exit:retmoveax,canWritecmpeax,0jleexitmoveax,-1movcanWrite,eax....exit:ret將某些操作為原子操作仍是多行代碼,看作一個原子操作Interlocked類AddCompareExchangeDecrementExchangeIncrementReadInterlocked.AddAdd(int,int)將一次整數加法作為原子操作進行結果放在第一個參數中不會出現加法做完一半的情況Interlocked.CompareExchangeCompareExchange(refintp1,intvalue,intp2);如果p1==p2,就p1=value,并返回原來p1的值同樣,原子操作。改進的簡單的同步辦法classProgram{staticint
canRead=1;staticint
canWrite=1;staticvoidMain(string[]args){Threadread1=newThread(ReadThread);read1.Start();Threadread2=newThread(ReadThread);read2.Start();Threadwrite1=newThread(WriteThread);read1.Start();Threadwrite2=newThread(WriteThread);write2.Start();}
staticpublicvoidWriteThread(){
if(canWrite==1){
Interlocked.Add(canWrite,-1);Interlocked.Add(canRead,-1);
//canWrite=false;
canRead=false;//寫數據}
Interlocked.Add(canWrite,-1);Interlocked.Add(canRead,-1);//
canWrite=true;
canRead=true;}仍存在的問題對canWrite和canRead的操作仍不是原子的canWrite==1的比較,也不是原子的
staticpublicvoidWriteThread(){
if(canWrite==1){
Interlocked.Add(canWrite,-1);Interlocked.Add(canRead,-1);
//canWrite=false;
canRead=false;//寫數據}
Interlocked.Add(canWrite,-1);Interlocked.Add(canRead,-1);//
canWrite=true;
canRead=true;}lock語句2024/4/2936lock語句的功能
lock語句代碼段(語句塊)標記為臨界區。它能確保當一個線程位于代碼的臨界區(可以理解為一段代碼)時,另一個線程不進入臨界區。如果其他線程試圖進入鎖定的代碼段,則它將一直等待(即被阻塞),直到鎖定的對象被釋放以后才能進入臨界區。lock語句的用法首先利用lock語句鎖定某一個對象,然后執行代碼段中的語句,等代碼段中的語句執行完畢后,再釋放該對象。privateObjectobj=newObject();……lock(obj){//臨界區中的代碼}lock語句2024/4/2937使用lock語句應注意的問題:鎖定的對象名(上面代碼中的obj)一般聲明為Object類型,不要將其聲明為值類型。鎖定的對象名不能將其聲明為public,只能為private臨界區中的代碼一般不宜太多。線程池2024/4/2938背景:
1)無限制的創建線程消耗系統資源
2)創建線程、回收線程均需要時間線程池:是在后臺執行多個任務的線程集合。
1)最大線程數限制。如果所有線程都繁忙,則額外的任務將放入等待隊列中,直到有線程可用時才能夠得到處理。
2)最小線程數=創建線程池時應立即啟動的數目
3)一旦池中的某個線程完成任務,它將返回到等待線程隊列中,等待被再次使用。這種重用使應用程序可以避免為每個任務創建新線程引起的資源和時間消耗。
4)一項工作任務被加入到線程池的隊列中,就不能取消該任務,直到該任務完成。線程池2024/4/2939為什么要用線程池?降低系統開銷可以重用資源,使應用程序可以避免為每個任務創建新線程引起的資源和時間消耗。什么情況下才使用線程池?后臺執行,而且不同線程沒有優先級區別適用于需要多個線程而實際執行時間又不多的場合沒有導致線程長時間被阻塞的任務(對于可能長時間被阻塞的任務,應該創建單獨的線程處理,不應該使用線程池),這是因為線程池具有最大線程數限制,大量阻塞的線程池線程可能會阻止任務啟動線程池
2024/4/2940ThreadPool類位于System.Threading命名空間下。ThreadPool提供了對線程池的操作(靜態方法),例如:發送工作項、處理異步I/O、設置線程數目等ThreadPool是一個靜態類托管線程池中的線程為后臺線程,即它們的IsBackground屬性為true。這意味著在所有的前臺線程都已退出后,ThreadPool線程也會自動退出線程池2024/4/2941GetAvailableThreads方法:檢索由GetMaxThreads返回的線程池線程的最大數目和當前活動數目之間的差值GetMaxThreads方法:檢索可以同時處于活動狀態的線程池請求的數目。所有大于此數目的請求將保持排隊狀態,直到線程池線程變為可用GetMinThreads方法:檢索線程池在新請求預測中維護的空閑線程數SetMaxThreads方法:可以同時處于活動狀態的線程池的請求數目。所有大于此數目的請求將保持排隊狀態,直到線程池線程變為可用。SetMinThreads方法:設置線程池在新請求預測中維護的空閑線程數線程池2024/4/2942QueueUserWorkItem方法功能:功能:請求線程池處理一個任務或者工作項運行時線程池會自動為每一個任務創建線程并且在任務釋放時釋放線程。語法:帶一個
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 遼寧中醫藥大學杏林學院《計算復雜性》2023-2024學年第二學期期末試卷
- 湘南學院《大學體育V》2023-2024學年第一學期期末試卷
- 沙洲職業工學院《版面設計與軟件應用》2023-2024學年第二學期期末試卷
- 江蘇省鹽城市大豐區實驗初級中學2024-2025學年初三下期4月月考復習語文試題試卷含解析
- 江門市重點中學2025年初三沖刺中考最后1卷化學試題含解析
- 武漢華夏理工學院《市場營銷學原理》2023-2024學年第二學期期末試卷
- 麗江職業技術學院《英語基礎寫作(二)》2023-2024學年第一學期期末試卷
- 內蒙古鴻德文理學院《車橋耦合振動》2023-2024學年第二學期期末試卷
- 羊只買賣合同范本
- 長沙理工大學城南學院《英語精讀(3)》2023-2024學年第一學期期末試卷
- 川教版(2024)小學信息技術三年級上冊《跨學科主題活動-在線健康小達人》教學實錄
- 2025中考物理總復習填空題練習100題(附答案及解析)
- 機械專業英語
- 高空作業車(剪叉式、曲臂式)驗收表
- 廣東省廣州市2024屆高三下學期一模考試 政治 含解析
- 血透患者敘事護理故事
- 義務教育小學科學課程標準-2022版
- 江西省南昌市2023-2024學年八年級下學期期中英語試題(含聽力)【含答案解析】
- 2024年全國國家版圖知識競賽題庫及答案
- 新教師三筆字培訓課件
- 藍色西湖大學頂部導航欄博士碩士研究生畢業論文答辯模板.x
評論
0/150
提交評論