可視化程序設計.多線程技術_第1頁
可視化程序設計.多線程技術_第2頁
可視化程序設計.多線程技術_第3頁
可視化程序設計.多線程技術_第4頁
可視化程序設計.多線程技術_第5頁
已閱讀5頁,還剩42頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

2024/4/29可視化程序設計主講:周建偉1內容提要進程與線程的概念應用程序域在C#中使用多線程線程同步問題線程同步的基本方法進程與線程的基本概念2024/4/293進程正在執(zhí)行的程序稱為進程。與進程相關的信息包括:進程標示(進程ID)、文件名、執(zhí)行的程序和數(shù)據(jù),運行時間、在存儲器中的位置、占用的內存容量等。線程將一個進程劃分為若干個獨立的執(zhí)行流,每一個執(zhí)行流均稱為一個線程。(1)線程是CPU調度和分配的基本單位。(2)每個進程都有一個主線程。(3)除了主線程以外,還可以給一個進程分配若干個子線程,從而達到多個任務并行執(zhí)行的目的。進程(超市)食品服裝體育用品文具數(shù)據(jù)(商品)線程(收銀臺)CPU(收銀員)多線程應用程序域AppDomain把進程的4G空間又做了劃分把一個大屋子進一步隔成多個小屋子從這個意義上,AppDomain是“亞進程”兩個應用程序域占用獨立的數(shù)據(jù)空間,且不能互相訪問地址不能相同,因為在同一個進程里面代碼空間可以重疊,相當于一個程序啟動多遍線程同一時刻只能在一個應用程序域中運行默認的AppDomain是整個進程空間食品AppDomain(承包區(qū))進程(超市)服裝AppDomain家電AppDomain線程仍直屬進程,它們可以先后運行于不同的AppDomain(收款臺直屬超市收完買服裝的再收買食品的)進程管理(Process類)2024/4/297Process類常用的屬性和方法-----------------------獲取進程實例-------------------GetProcessById方法(靜態(tài)方法):通過進程Id創(chuàng)建新的Process組件,并將其與本地計算機上的進程資源關聯(lián)。GetProcessById最多只有一個Process實例。GetProcesses方法(靜態(tài)方法):獲取本機所有進程GetProcessesByName方法(靜態(tài)方法):獲取本機上特定名稱的進程-----------------------獲取及設置優(yōu)先級---------------BasePriority屬性:獲取進程優(yōu)先級(只讀)PriorityClass屬性:設置或更改進程優(yōu)先級進程管理(Process類)2024/4/298---------------------------進程ID及進程名-----------------------Id屬性:獲取關聯(lián)進程的唯一標識符ProcessName屬性:獲取該進程的名稱,不包括路徑和擴展名-----------------------------進程其他信息-------------------------------MachineName屬性:獲取關聯(lián)進程正在其上運行的計算機名稱MainModule屬性:獲取關聯(lián)進程的主模塊Modules屬性:獲取由關聯(lián)進程加載的模塊TotalProcessorTime屬性:獲取進程的總的處理器時間StartTime屬性:獲取關聯(lián)進程的啟動時間WorkingSet64屬性:為進程分配的物理內存量(字節(jié)數(shù))進程管理(Process類)2024/4/299-----------------------進程啟動-------------------------Start方法:啟動進程資源并將其與Process組件關聯(lián)StartInfo屬性:獲取或設置要傳遞給啟動進程的文件名以及啟動參數(shù)-----------------------進程終止-------------------------Kill方法:強制終止進程CloseMainWindow方法:關閉具有用戶界面的進程Close方法:釋放與此組件關聯(lián)的所有資源HasExited屬性:指示關聯(lián)進程是否已終止WaitForExit方法:設置等待關聯(lián)進程退出的時間,并在該段時間結束前或該進程退出前,阻止當前線程執(zhí)行。獲取進程信息2024/4/29101、如何獲取進程信息(1)獲取本地計算機的所有進程:

Process[]myProcesses=Process.GetProcesses();(2)獲取本地計算機上指定名稱的進程:

Process[]myProcesses=

Process.GetProcessesByName("進程名稱");注意:(a)進程名稱不帶擴展名。(b)可以是任何一個可執(zhí)行文件例如:

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)創(chuàng)建一個Process組件的實例,例如:

ProcessmyProcess=newProcess();(2)設置其對應的StartInfo屬性,指定要運行的應用程序名以及傳遞的參數(shù):

myProcess.StartInfo.FileName="文件名";

process1.StartInfo.Arguments="參數(shù)";如果該進程帶有圖形用戶界面,也可以指定圖形用戶界面的打開方式。例如:

myProcess.StartInfo.WindowStyle=ProcessWindowStyle.Normal;(3)調用該實例的Start方法啟動該進程。方法2:

直接調用Process類提供的靜態(tài)方法啟動進程。啟動和停止進程2024/4/29132.停止進程通過兩種方法利用Process組件停止進程。(1)如果進程有圖形用戶界面,調用CloseMainWindow方法。(2)如果進程沒有用戶界面,調用進程的Kill方法。不論有沒有圖形用戶界面,如果希望強行讓其退出,在權限允許的情況下,均可以調用Kill方法終止該進程。線程管理(Thread類)2024/4/2914Thread類位于System.Threading命名空間下。Thread類是用于創(chuàng)建和控制線程的,對線程的常用操作有:啟動線程、終止線程、合并線程和讓線程休眠等。Thread類提供的常用屬性IsAlive屬性:獲取一個值,該值指示當前線程的執(zhí)行狀態(tài)。如果此線程已啟動并且尚未正常終止,則為true;否則為falseIsBackground屬性:獲取或設置一個值,該值指示某個線程是否為后臺線程。是后臺線程或即將成為后臺線程,則為true;否則為falsePriority屬性:獲取或設置一個值,該值指示線程的調度優(yōu)先級線程管理(Thread類)2024/4/2915Thread類提供的常用方法Start方法:啟動線程Join方法:將指定的線程合并到當前線程中,并阻止當前線程執(zhí)行,直到指定的線程終止或經(jīng)過了指定的時間為止Sleep方法:將當前線程阻止指定的毫秒數(shù),零(0)表示應掛起此線程以使其他等待線程能夠執(zhí)行Abort方法:在調用此方法的線程上引發(fā)ThreadAbortException,以開始終止此線程的過程。調用此方法通常會終止線程前臺線程和后臺線程2024/4/2916一個線程要么是后臺線程要么是前臺線程。后臺線程與前臺線程類似,區(qū)別是后臺線程不會影響進程終止。屬于某個進程的所有前臺線程都終止后,公共語言運行庫就會結束該進程,而且所有屬于該進程的后臺線程也都會立即停止,而不管后臺工作是否完成。利用Thread對象的IsBackground屬性,可以設置或判斷一個線程是后臺線程還是前臺線程。通過將某個線程的IsBackground屬性設置為true,使其變?yōu)楹笈_線程。默認情況下,屬于托管線程池的線程(即其IsThreadPoolThread屬性為true的線程)都是后臺線程,通過創(chuàng)建并啟動新的Thread對象而生成的線程都是前臺線程。線程的基本操作2024/4/29171.啟動線程啟動線程前,首先要創(chuàng)建一個線程。創(chuàng)建無參數(shù)線程的一般形式為:

Threadt1=newThread(線程名);創(chuàng)建帶參數(shù)線程的一般形式為(傳遞一個Object類型的參數(shù)):

Threadt2=newThread(線程名(Objectobj));創(chuàng)建線程實例后,就可以調用Start方法啟動線程了。例如:

t1.Start();//不帶參數(shù)

t2.Start(“myClass”);//帶參數(shù)注意:調用Start只是告訴系統(tǒng)啟動該線程,但是系統(tǒng)并不一定會立即啟動它。線程的基本操作2024/4/29182.終止線程

兩種方法:事先設置一個布爾字段,在其他線程中通過修改該布爾量的值作為傳遞給該線程是否需要終止的判斷條件,而在該線程中循環(huán)判斷該布爾值,以確定是否退出線程,這是結束線程比較好的方法,實際應用中一般使用這種方法。調用Thread類的Abort方法,該方法的最終效果是強行終止線程。線程的基本操作2024/4/29193.暫停線程在多線程應用程序中,有時候并不希望某一個線程繼續(xù)執(zhí)行,而是希望該線程暫停一段時間,這樣,CPU就會將其時間片中剩余的部分讓給另一個線程。調用Thread類的Sleep方法可以實現(xiàn)這個功能。例如:

Thread.Sleep(1000);

這條語句的功能是讓當前線程暫停1000毫秒。注意

Sleep方法是靜態(tài)方法,暫停的是該語句所在的線程,而不是其他線程。線程的基本操作2024/4/29204.合并線程Join方法用于把指定的線程合并到當前線程中,從而使其變?yōu)橐粋€單個的線程。如果一個線程t1在執(zhí)行的過程中需要等待另一個線程t2結束后才能繼續(xù)執(zhí)行,可以在t1的代碼塊中調用t2的join方法。例如:

t2.Join();

功能:t1在執(zhí)行到t2.Join()語句后,就處于暫停狀態(tài),直到t2結束后才會繼續(xù)執(zhí)行。為了避免t1一直等待,可以在調用t2的Join方法的時候指定一個暫停時間,例如:t2.Join(100);在一個線程中操作另一個線程的控件2024/4/2921默認情況下,在Windows應用程序中,.NETFramework不允許在一個線程中直接操作另一個線程中的控件,這是因為訪問Windows窗體控件本質上不是線程安全的。在應用程序中,如果創(chuàng)建某控件的線程之外的其他線程試圖調用該控件,則系統(tǒng)會引發(fā)一個InvalidOperationException異常。有兩種辦法可以解決這個問題:(1)使用委托(delegate)操作另一個線程中的控件(2)用BackgroundWorker組件在后臺執(zhí)行線程在一個線程中操作另一個線程的控件(續(xù))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);}線程的優(yōu)先級2024/4/2924五個優(yōu)先級,由高到低分別是:Highest、AboveNormal、

Normal(默認)、BelowNormal和Lowest可以使用下面的方法為其賦予較高的優(yōu)先級:

Threadt=newThread(MethodName);t.priority=ThreadPriority.AboveNormal;通過設置線程的優(yōu)先級可以改變線程的執(zhí)行順序,所設置的優(yōu)先級僅僅適用于這些線程所屬的進程。注意:當把某線程的優(yōu)先級設置為Highest時,系統(tǒng)正在運行的其他線程都會終止,所以使用這個優(yōu)先級別時要特別小心。線程同步2024/4/2925為什么要同步 如果不同步,線程訪問共享資源時可能出錯對象讀取讀取寫入寫入線程的數(shù)據(jù)訪問線程體是代碼,代碼要訪問數(shù)據(jù)兩個線程同時要求訪問同一個數(shù)據(jù)?DataSetds=CreateDataSet();//......dataGridView1.DataSource=ds;DataSetds=CreateDataSet();foreach(DataTabledtinds.Tables{//....}ds.Tables.Add(newDataTable())//....//.....線程同步確保進程內的一個資源不能同時被寫同時寫,結果不可預知可以同時讀,因為數(shù)據(jù)并不改變寫的時候也不能讀,數(shù)據(jù)不完整策略:確保寫操作只有一個線程可執(zhí)行。一個線程寫的時候,其它線程全阻止(不能讀也不能寫)寫完后,允許其它線程訪問。如果下一個訪問的線程也是寫,則又一次阻止除自己外的所有線程沒人寫,不限制。線程同步2024/4/2928解決方法:System.Threading命名空間提供了多個用于同步線程的類這些類包括Mutex、Monitor、Interlocked等。在實際應用中經(jīng)常使用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;//寫數(shù)據(jù)

}

canWrite=true;

canRead=true;}staticpublicvoidReadThread(){

if(canRead){

canWrite=false;//讀數(shù)據(jù)

}

canWrite=true;}}問題:非原子操作if(canWrite){canWrite=false//...}moveax,canWritecmpeax,0jleexitmoveax,-1movcanWrite,eax....exit:retmoveax,canWritecmpeax,0jleexitmoveax,-1movcanWrite,eax....exit:ret將某些操作為原子操作仍是多行代碼,看作一個原子操作Interlocked類AddCompareExchangeDecrementExchangeIncrementReadInterlocked.AddAdd(int,int)將一次整數(shù)加法作為原子操作進行結果放在第一個參數(shù)中不會出現(xiàn)加法做完一半的情況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;//寫數(shù)據(jù)}

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;//寫數(shù)據(jù)}

Interlocked.Add(canWrite,-1);Interlocked.Add(canRead,-1);//

canWrite=true;

canRead=true;}lock語句2024/4/2936lock語句的功能

lock語句代碼段(語句塊)標記為臨界區(qū)。它能確保當一個線程位于代碼的臨界區(qū)(可以理解為一段代碼)時,另一個線程不進入臨界區(qū)。如果其他線程試圖進入鎖定的代碼段,則它將一直等待(即被阻塞),直到鎖定的對象被釋放以后才能進入臨界區(qū)。lock語句的用法首先利用lock語句鎖定某一個對象,然后執(zhí)行代碼段中的語句,等代碼段中的語句執(zhí)行完畢后,再釋放該對象。privateObjectobj=newObject();……lock(obj){//臨界區(qū)中的代碼}lock語句2024/4/2937使用lock語句應注意的問題:鎖定的對象名(上面代碼中的obj)一般聲明為Object類型,不要將其聲明為值類型。鎖定的對象名不能將其聲明為public,只能為private臨界區(qū)中的代碼一般不宜太多。線程池2024/4/2938背景:

1)無限制的創(chuàng)建線程消耗系統(tǒng)資源

2)創(chuàng)建線程、回收線程均需要時間線程池:是在后臺執(zhí)行多個任務的線程集合。

1)最大線程數(shù)限制。如果所有線程都繁忙,則額外的任務將放入等待隊列中,直到有線程可用時才能夠得到處理。

2)最小線程數(shù)=創(chuàng)建線程池時應立即啟動的數(shù)目

3)一旦池中的某個線程完成任務,它將返回到等待線程隊列中,等待被再次使用。這種重用使應用程序可以避免為每個任務創(chuàng)建新線程引起的資源和時間消耗。

4)一項工作任務被加入到線程池的隊列中,就不能取消該任務,直到該任務完成。線程池2024/4/2939為什么要用線程池?降低系統(tǒng)開銷可以重用資源,使應用程序可以避免為每個任務創(chuàng)建新線程引起的資源和時間消耗。什么情況下才使用線程池?后臺執(zhí)行,而且不同線程沒有優(yōu)先級區(qū)別適用于需要多個線程而實際執(zhí)行時間又不多的場合沒有導致線程長時間被阻塞的任務(對于可能長時間被阻塞的任務,應該創(chuàng)建單獨的線程處理,不應該使用線程池),這是因為線程池具有最大線程數(shù)限制,大量阻塞的線程池線程可能會阻止任務啟動線程池

2024/4/2940ThreadPool類位于System.Threading命名空間下。ThreadPool提供了對線程池的操作(靜態(tài)方法),例如:發(fā)送工作項、處理異步I/O、設置線程數(shù)目等ThreadPool是一個靜態(tài)類托管線程池中的線程為后臺線程,即它們的IsBackground屬性為true。這意味著在所有的前臺線程都已退出后,ThreadPool線程也會自動退出線程池2024/4/2941GetAvailableThreads方法:檢索由GetMaxThreads返回的線程池線程的最大數(shù)目和當前活動數(shù)目之間的差值GetMaxThreads方法:檢索可以同時處于活動狀態(tài)的線程池請求的數(shù)目。所有大于此數(shù)目的請求將保持排隊狀態(tài),直到線程池線程變?yōu)榭捎肎etMinThreads方法:檢索線程池在新請求預測中維護的空閑線程數(shù)SetMaxThreads方法:可以同時處于活動狀態(tài)的線程池的請求數(shù)目。所有大于此數(shù)目的請求將保持排隊狀態(tài),直到線程池線程變?yōu)榭捎谩etMinThreads方法:設置線程池在新請求預測中維護的空閑線程數(shù)線程池2024/4/2942QueueUserWorkItem方法功能:功能:請求線程池處理一個任務或者工作項運行時線程池會自動為每一個任務創(chuàng)建線程并且在任務釋放時釋放線程。語法:帶一個

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論