![VC#中的多線程編程_第1頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/15/34050438-3849-4079-866d-b4d696bf0d63/34050438-3849-4079-866d-b4d696bf0d631.gif)
![VC#中的多線程編程_第2頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/15/34050438-3849-4079-866d-b4d696bf0d63/34050438-3849-4079-866d-b4d696bf0d632.gif)
![VC#中的多線程編程_第3頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/15/34050438-3849-4079-866d-b4d696bf0d63/34050438-3849-4079-866d-b4d696bf0d633.gif)
![VC#中的多線程編程_第4頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/15/34050438-3849-4079-866d-b4d696bf0d63/34050438-3849-4079-866d-b4d696bf0d634.gif)
![VC#中的多線程編程_第5頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/15/34050438-3849-4079-866d-b4d696bf0d63/34050438-3849-4079-866d-b4d696bf0d635.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、Visual C#中的多線程編程C#是.Net平臺的通用開發(fā)工具,它能夠建造所有的.Net應(yīng)用。在.Net中所有線程都運(yùn)行在應(yīng)用程序域(AppDomain)中,這也許讓你想到Win32進(jìn)程,實(shí)際上它們還是有很大的不同。應(yīng)用程序域提供了一種安全而通用的處理單元,公共語言運(yùn)行庫可使用它來隔離應(yīng)用程序。注意在.Net中應(yīng)用程序的隔離是應(yīng)用程序域而不是進(jìn)程,在單個(gè)進(jìn)程中可以存在幾個(gè)應(yīng)用程序域,而且線程可以跨越應(yīng)用程序域的范圍,某個(gè)線程中的方法可以調(diào)用另一個(gè)線程的方法,這樣的話就不會造成進(jìn)程間調(diào)用或進(jìn)程間切換等方面的額外開銷??梢哉f應(yīng)用程序域是物理進(jìn)程(也即win32中的Process)內(nèi)的邏輯進(jìn)程。在
2、Visul C#中System.Threading 命名空間提供一些使得可以進(jìn)行多線程編程的類和接口,其中線程的創(chuàng)建有以下三種方法:Thread、ThreadPool、Timer。下面我就它們的使用方法逐個(gè)作一簡單介紹。1 Thread這也許是最復(fù)雜的方法,但它提供了對線程的各種靈活控制。首先你必須使用它的構(gòu)造函數(shù)創(chuàng)建一個(gè)線程實(shí)例,它的參數(shù)比較簡單,只有一個(gè)ThreadStart 委托:C#public Thread(ThreadStart start);然后調(diào)用Start()啟動它,當(dāng)然你可以利用它的Priority屬性來設(shè)置或獲得它的運(yùn)行優(yōu)先級(enum ThreadPriori
3、ty: Normal、 Lowest、 Highest、 BelowNormal、 AboveNormal)。見下例:它首先生成了兩個(gè)線程實(shí)例t1和t2,然后分別設(shè)置它們的優(yōu)先級,接著啟動兩線程(兩線程基本一樣,只不過它們輸出不一樣,t1為“1”,t2為“2”,根據(jù)它們各自輸出字符個(gè)數(shù)比可大致看出它們占用CPU時(shí)間之比,這也反映出了它們各自的優(yōu)先級)。 static void Main(string args) Thread t1 = new Thread(new ThreadStart(Thread1);
4、0; Thread t2 = new Thread(new ThreadStart(Thread2); t1.Priority = ThreadPriority.BelowNormal ; t2.Priority = ThreadPriority.Lowest ; t1.Start(); t2.Start(); public static void Thread1()
5、0; for (int i = 1; i < 1000; i+) /每運(yùn)行一個(gè)循環(huán)就寫一個(gè)“1”dosth(); Console.Write("1"); public static void Thread2() for (int i = 0; i < 1000; i+) /
6、每運(yùn)行一個(gè)循環(huán)就寫一個(gè)“2” dosth(); Console.Write("2"); public static void dosth() /用來模擬復(fù)雜運(yùn)算 for (int j = 0; j < 10000000; j+)
7、160;int a=15; a = a*a*a*a; 以上程序運(yùn)行結(jié)果為:推薦精選111111111111111111111111111111111111111111211111111111111111111111111111111111111111121111111111111111111111111111111111111111112111111111111111111111111111111111111111111211111111111111111111111111111111111
8、111111121111111111111111111111111111111111111111112 從以上結(jié)果我們可以看出,t1線程所占用CPU的時(shí)間遠(yuǎn)比t2的多,這是因?yàn)閠1的優(yōu)先級比t2的高,若我們把t1和t2的優(yōu)先級都設(shè)為Normal,那結(jié)果是如何?它們所占用的CPU時(shí)間會一樣嗎?是的,正如你所料,見下圖: 12121122121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212
9、1212推薦精選121212121212121212 從上例我們可看出,它的構(gòu)造類似于win32的工作線程,但更加簡單,只需把線程要調(diào)用的函數(shù)作為委托,然后把委托作為參數(shù)構(gòu)造線程實(shí)例即可。當(dāng)調(diào)用Start()啟動后,便會調(diào)用相應(yīng)的函數(shù),從那函數(shù)第一行開始執(zhí)行。 接下來我們結(jié)合線程的ThreadState屬性來了解線程的控制。ThreadState是一個(gè)枚舉類型,它反映的是線程所處的狀態(tài)。當(dāng)一個(gè)Thread實(shí)例剛創(chuàng)建時(shí),它的ThreadState是Unstarted;當(dāng)此線程被調(diào)用Start()啟動之后,它的ThreadState是 Runn
10、ing; 在此線程啟動之后,如果想讓它暫停(阻塞),可以調(diào)用Thread.Sleep() 方法,它有兩個(gè)重載方法(Sleep(int )、Sleep(Timespan )),只不過是表示時(shí)間量的格式不同而已,當(dāng)在某線程內(nèi)調(diào)用此函數(shù)時(shí),它表示此線程將阻塞一段時(shí)間(時(shí)間是由傳遞給 Sleep 的毫秒數(shù)或Timespan決定的,但若參數(shù)為0則表示掛起此線程以使其它線程能夠執(zhí)行,指定 Infinite 以無限期阻塞線程),此時(shí)它的ThreadState將變?yōu)閃aitSleepJoin,另外值得注意一點(diǎn)的是Sleep()函數(shù)被定義為了static?! 這也意味著它不能和某個(gè)線程實(shí)例結(jié)合起來用,也即不存在
11、類似于t1.Sleep(10)的調(diào)用!正是如此,Sleep()函數(shù)只能由需“Sleep”的線程自己調(diào)用,不允許其它線程調(diào)用,正如when to Sleep是個(gè)人私事不能由它人決定。但是當(dāng)某線程處于WaitSleepJoin狀態(tài)而又不得不喚醒它時(shí),可使用Thread.Interrupt 方法 ,它將在線程上引發(fā)ThreadInterruptedException,下面我們先看一個(gè)例子(注意Sleep的調(diào)用方法):static void Main(string args) Thread t1 = new Thread(new Thread
12、Start(Thread1); t1.Start(); t1.Interrupt ();E.WaitOne ();t1.Interrupt (); t1.Join(); Console.WriteLine(“t1 is end”); static AutoResetEvent E = new AutoResetEvent(false); public static void Thread1()
13、60; try /從參數(shù)可看出將導(dǎo)致休眠 Thread.Sleep(Timeout.Infinite); catch(System.Threading.ThreadInterruptedException e) /中斷處理程序 Console.WriteLine (" 1st interrupt");
14、; E.Set (); try / 休眠 Thread.Sleep(Timeout.Infinite ); catch(System.Threading.ThreadInterruptedException e) Console.WriteLine (" 2nd interrupt"); /暫停10秒&
15、#160; Thread.Sleep (10000); 運(yùn)行結(jié)果為: 1st interrupt 2nd interrupt (10s后)t1 is end 從上例我們可以看出Thread.Interrupt方法可以把程序從某個(gè)阻塞(WaitSleepJoin)狀態(tài)喚醒進(jìn)入對應(yīng)的中斷處理程序,然后繼續(xù)往下執(zhí)行(它的ThreadState也變?yōu)镽unning),此函數(shù)的使用必須注意以下幾點(diǎn):1 .此方法不僅可喚醒由Sleep導(dǎo)致的阻塞,而且對一切可導(dǎo)致線程進(jìn)入WaitSleepJoin狀態(tài)的方法(如Wait和Join)都有效。
16、如上例所示, 使用時(shí)要把導(dǎo)致線程阻塞的方法放入try塊內(nèi), 并把相應(yīng)的中斷處理程序放入catch塊內(nèi)。2 .對某一線程調(diào)用Interrupt, 如它正處于WaitSleepJoin狀態(tài), 則進(jìn)入相應(yīng)的中斷處理程序執(zhí)行, 若此時(shí)它不處于WaitSleepJoin狀態(tài), 則它后來進(jìn)入此狀態(tài)時(shí), 將被立即中斷。若在中斷前調(diào)用幾次Interrupt, 只有第一次調(diào)用有效, 這正是上例我用同步的原因, 這樣才能確保第二次調(diào)用Interrupt在第一個(gè)中斷后調(diào)用,否則的話可能導(dǎo)致第二次調(diào)用無效(若
17、它在第一個(gè)中斷前調(diào)用)。你可以把同步去掉試試,其結(jié)果很可能是: 1st interrupt上例還用了另外兩個(gè)使線程進(jìn)入WaitSleepJoin狀態(tài)的方法:利用同步對象和Thread.Join方法。Join方法的使用比較簡單,它表示在調(diào)用此方法的當(dāng)前線程阻塞直至另一線程(此例中是t1)終止或者經(jīng)過了指定的時(shí)間為止(若它還帶了時(shí)間量參數(shù)),當(dāng)兩個(gè)條件(若有)任一出現(xiàn),它立即結(jié)束WaitSleepJoin狀態(tài)進(jìn)入Running狀態(tài)(可根據(jù).Join方法的返回值判斷為何種條件,為true,則是線程終止;false則是時(shí)間到)。線程的暫停還可用Thread.Suspend方法,
18、當(dāng)某線程處于Running狀態(tài)時(shí)對它調(diào)用Suspend方法,它將進(jìn)入SuspendRequested狀態(tài),但它并不會被立即掛起,直到線程到達(dá)安全點(diǎn)之后它才可以將該線程掛起,此時(shí)它將進(jìn)入Suspended狀態(tài)。如對一個(gè)已處于Suspended的線程調(diào)用則無效,要恢復(fù)運(yùn)行只需調(diào)用Thread.Resume即可。 最后我們談的是線程的銷毀,我們可以對需銷毀的線程調(diào)用Abort方法,它會在此線程上引發(fā)ThreadAbortException。我們可把線程內(nèi)的一些代碼放入try塊內(nèi),并把相應(yīng)處理代碼放入相應(yīng)的catch塊內(nèi),當(dāng)線程正執(zhí)行try塊內(nèi)代碼時(shí)如被調(diào)用Abort,它便會跳入相應(yīng)的ca
19、tch塊內(nèi)執(zhí)行,執(zhí)行完catch快內(nèi)的代碼后它將終止(若catch塊內(nèi)執(zhí)行了ResetAbort則不同了:它將取消當(dāng)前Abort請求,繼續(xù)向下執(zhí)行。所以如要確保某線程終止的最好用Join,如上例)。2 ThreadPool線程池(ThreadPool)是一種相對較簡單的方法,它適應(yīng)于一些需要多個(gè)線程而又較短任務(wù)(如一些常處于阻塞狀態(tài)的線程) ,它的缺點(diǎn)是對創(chuàng)建的線程不能加以控制,也不能設(shè)置其優(yōu)先級。由于每個(gè)進(jìn)程只有一個(gè)線程池,當(dāng)然每個(gè)應(yīng)用程序域也只有一個(gè)線程池(對線),所以你將發(fā)現(xiàn)ThreadPool類的成員函數(shù)都為static! 當(dāng)你首次調(diào)用ThreadPool.QueueUser
20、WorkItem、ThreadPool.RegisterWaitForSingleObject等,便會創(chuàng)建線程池實(shí)例。下面我就線程池當(dāng)中的兩函數(shù)作一介紹:C#public static bool QueueUserWorkItem( 推薦精選/調(diào)用成功則返回trueWaitCallback callBack,/要?jiǎng)?chuàng)建的線程調(diào)用的委托 object state /傳遞給委托的參數(shù))/它的另一個(gè)重載函數(shù)類似,只是委托不帶參數(shù)而已 此函數(shù)的作用是把要?jiǎng)?chuàng)建的線程排隊(duì)到線程池,當(dāng)線程池的可用線程數(shù)不為零時(shí)(線程池有創(chuàng)建線程數(shù)的限制,缺身值為25),便創(chuàng)建此線程,否則就排隊(duì)到線程池等到它有可用
21、的線程時(shí)才創(chuàng)建。C#public static RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject,/ 要注冊的 WaitHandle WaitOrTimerCallback callBack,/ 線程調(diào)用的委托 object state,/傳遞給委托的參數(shù) int TimeOut,/超時(shí),單位為毫秒, bool executeOnlyOnce file:/是否只執(zhí)行一次); publ
22、ic delegate void WaitOrTimerCallback( object state,/也即傳遞給委托的參數(shù) bool timedOut/true表示由于超時(shí)調(diào)用,反之則因?yàn)閣aitObject); 此函數(shù)的作用是創(chuàng)建一個(gè)等待線程,一旦調(diào)用此函數(shù)便創(chuàng)建此線程,在參數(shù)waitObject變?yōu)榻K止?fàn)顟B(tài)或所設(shè)定的時(shí)間TimeOut到了之前,它都處于“阻塞”狀態(tài),值得注意的一點(diǎn)是此“阻塞”與Thread的WaitSleepJoin狀態(tài)有很大的不同:當(dāng)某Thread處于WaitSleepJoin狀態(tài)時(shí)CPU會定期的喚醒它以輪詢更新狀態(tài)信息,
23、然后再次進(jìn)入WaitSleepJoin狀態(tài),線程的切換可是很費(fèi)資源的;而用此函數(shù)創(chuàng)建的線程則不同,在觸發(fā)它運(yùn)行之前,CPU不會切換到此線程,它既不占用CPU的時(shí)間又不浪費(fèi)線程切換時(shí)間,但CPU又如何知道何時(shí)運(yùn)行它?實(shí)際上線程池會生成一些輔助線程用來監(jiān)視這些觸發(fā)條件,一旦達(dá)到條件便啟動相應(yīng)的線程,當(dāng)然這些輔助線程本身也占用時(shí)間,但是如果你需創(chuàng)建較多的等待線程時(shí),使用線程池的優(yōu)勢就越加明顯。見下例:static AutoResetEvent ev=new AutoResetEvent(false); public static int Main(string args)
24、60; ThreadPool.RegisterWaitForSingleObject( ev, new WaitOrTimerCallback(WaitThreadFunc), 4, 2000, false/表示每次完成等待操作后都重置計(jì)時(shí)器,直到注銷等待 ); ThreadPool.QueueUserWorkItem (new WaitCallback (ThreadFunc),8); Thread.Sleep (10000); return 0;
25、0; public static void ThreadFunc(object b) Console.WriteLine ("the object is 0",b); for(int i=0;i<2;i+) Thread.Sleep (1000); ev.Set(); public static void WaitThreadFunc(object b,bool t)
26、; Console.WriteLine ("the object is 0,t is 1",b,t); 其運(yùn)行結(jié)果為: the object is 8the object is 4,t is Falsethe object is 4,t is Falsethe object is 4,t is Truethe object is 4,t is Truethe object is 4,t is True從以上結(jié)果我們可以看出線程ThreadFunc運(yùn)行了1次,而WaitThread
27、Func運(yùn)行了5次。我們可以從WaitOrTimerCallback中的bool t參數(shù)判斷啟動此線程的原因:t為false,則表示由于waitObject,否則則是由于超時(shí)。另外我們也可以通過object b向線程傳遞一些參數(shù)。3 Timer 它適用于需周期性調(diào)用的方法,它不在創(chuàng)建計(jì)時(shí)器的線程中運(yùn)行,它在由系統(tǒng)自動分配的單獨(dú)線程中運(yùn)行。這和Win32中的SetTimer方法類似。它的構(gòu)造為:C#public Timer( TimerCallback callback,/所需調(diào)用的方法 object
28、state,/傳遞給callback的參數(shù) int dueTime,/多久后開始調(diào)用callback int period/調(diào)用此方法的時(shí)間間隔);/ 如果 dueTime 為0,則 callback 立即執(zhí)行它的首次調(diào)用。如果 dueTime 為 Infinite,則 callback 不調(diào)用它的方法。計(jì)時(shí)器被禁用,但使用 Change 方法可以重新啟用它。如果 period 為0或 Infinite,并且 dueTime 不為 Infinite,則 callback 調(diào)用它的方法一次。計(jì)時(shí)器的定期行為被禁用,但使用 Change 方法可以重新啟用它。如果 period 為零 (0) 或 Infinite,并且 dueTime 不為 Infinite,則 callback 調(diào)用它的方法一次。計(jì)時(shí)器的定期行為被禁用,但使用 Change 方法可以重新啟用它。在創(chuàng)建計(jì)時(shí)器之后若想改變它的period和dueTime,我們可以通過調(diào)用Timer的Change方法來改變:C#public bool Change( int dueTime,
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 年產(chǎn)10萬臺新能源汽車電機(jī)控制器項(xiàng)目立項(xiàng)報(bào)告
- 色母粒項(xiàng)目安全風(fēng)險(xiǎn)評價(jià)報(bào)告
- 2021-2026年中國阿膠膏行業(yè)市場全景調(diào)研及投資規(guī)劃建議報(bào)告
- 中國區(qū)域產(chǎn)業(yè)規(guī)劃行業(yè)市場發(fā)展現(xiàn)狀及前景趨勢與投資分析研究報(bào)告(2024-2030版)
- 2025年沖吸泵行業(yè)深度研究分析報(bào)告
- 中國煙草機(jī)械翻新項(xiàng)目投資可行性研究報(bào)告
- 年產(chǎn)xxx輛倉儲搬運(yùn)車項(xiàng)目評估報(bào)告模板
- 塑膠安定劑項(xiàng)目可行性研究報(bào)告(模板)
- 2025年中國航標(biāo)涂料行業(yè)市場發(fā)展前景及發(fā)展趨勢與投資戰(zhàn)略研究報(bào)告
- 2025年企業(yè)自查報(bào)告參考范文
- 學(xué)校小賣部承包合同范文
- 普外腹腔鏡手術(shù)護(hù)理常規(guī)
- 2025年湖南鐵道職業(yè)技術(shù)學(xué)院高職單招職業(yè)技能測試近5年??及鎱⒖碱}庫含答案解析
- 2024年全國職業(yè)院校技能大賽(礦井災(zāi)害應(yīng)急救援賽項(xiàng))考試題庫(含答案)
- 《預(yù)制高強(qiáng)混凝土風(fēng)電塔筒生產(chǎn)技術(shù)規(guī)程》文本附編制說明
- 2025年浙江省溫州樂清市融媒體中心招聘4人歷年高頻重點(diǎn)提升(共500題)附帶答案詳解
- 2025年煤礦探放水證考試題庫
- C語言程序設(shè)計(jì) 教案
- 農(nóng)業(yè)機(jī)械設(shè)備運(yùn)輸及調(diào)試方案
- 2025新譯林版英語七年級下單詞表
- 海洋工程設(shè)備保溫保冷方案
評論
0/150
提交評論