實(shí)例代碼講解c# 線程(下)
前言
使用Mutex類
class Program { static void Main(string[] args) { const string MutexName ="CSharpThreadingCookbook"; using (var m = new Mutex(false, MutexName)) { if (!m.WaitOne(TimeSpan.FromSeconds(5), false)) { Console.WriteLine("Second instance is running!"); } else { Console.WriteLine("Runing!"); Console.ReadLine(); m.ReleaseMutex(); } } } }
當(dāng)主程序啟動(dòng)時(shí),定義了一個(gè)指定名稱的互斥量,設(shè)置initialowner標(biāo)志為false。這意味著如果互斥量已經(jīng)被創(chuàng)建,則允許程序獲取該互斥量。如果沒(méi)有獲取到互斥量,程序則簡(jiǎn)單的顯示running,的等待知道按下了任何鍵,然后釋放該互斥量并退出。 如果再運(yùn)行同樣一個(gè)程序,則會(huì)在5秒內(nèi)嘗試獲取互斥量。如果此時(shí)在第一個(gè)程序中按下了任何鍵,第二個(gè)程序則會(huì)開(kāi)始執(zhí)行。然而,如果保持等待5秒鐘,第二個(gè)程序?qū)o(wú)法獲取到該互斥量。 該方式可用于在不同的程序中同步線程,可被推廣到大量的使用場(chǎng)景中。
使用SemaphoreSilm類
static SemaphoreSlim _semaphore = new SemaphoreSlim(4); static void AccessDatabase(string name, int seconds) { Console.WriteLine("{0} waits to access a database",name); _semaphore.Wait(); Console.WriteLine("{0} was granted an access to a database",name); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("{0} is completed",name); _semaphore.Release(); }
static void Main(string[] args) { for (int i = 1; i <= 6; i++) { string threadName ="Thread" + i; int secondsToWait = 2 + 2 * i; var t = new Thread(() => AccessDatabase(threadName, secondsToWait)); t.Start(); } Console.ReadKey(); }
當(dāng)主程序啟動(dòng)時(shí),創(chuàng)建了SemaphoreSlim的一個(gè)實(shí)例,并在其構(gòu)造函數(shù)中指定允許的并發(fā)線程數(shù)量。然后啟動(dòng)了6個(gè)不同名稱和不同初始運(yùn)行時(shí)間的線程。每個(gè)線程都嘗試獲取數(shù)據(jù)庫(kù)的訪問(wèn),但是我們借助于信號(hào)系統(tǒng)限制了訪問(wèn)數(shù)據(jù)庫(kù)的并發(fā)數(shù)為4個(gè)線程。當(dāng)有4個(gè)線程獲取數(shù)據(jù)庫(kù)的訪問(wèn)后,其他兩個(gè)線程需要等待,直到之前線程中的某一個(gè)完成工作并調(diào)用_semaphore.Release方法來(lái)發(fā)出信號(hào)。
使用AutoResetEvent類
private staticAutoResetEvent _workerEvent=new AutoResetEvent(false); private staticAutoResetEvent _mainEvent =new AutoResetEvent(false); static void Process(int seconds) { Console.WriteLine("Starting a long running work... "); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("Work is done!"); _workerEvent.Set(); Console.WriteLine("Waiting for a main thread to complete its work"); _mainEvent.WaitOne(); Console.WriteLine("starting second operation... "); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("Work is done!"); _workerEvent.Set(); }
static void Main(string[] args) { var t = new Thread(() => Process(10)); t.Start(); Console.WriteLine("Waiting for a main thread to complete its work"); _workerEvent.WaitOne(); Console.WriteLine("First operation is completed!"); Console.WriteLine("Performing an operation on a main thread"); Thread.Sleep(TimeSpan.FromSeconds(5)); _mainEvent.Set(); Console.WriteLine("Now running the second operation on a second thread"); _workerEvent.WaitOne(); Console.WriteLine("Second operation is completed!"); }
當(dāng)主程序啟動(dòng)時(shí),定義了兩個(gè)autoresetEvent實(shí)例。其中一個(gè)是從子線程向主線程發(fā)信號(hào),另一個(gè)實(shí)例是從主線程向子線程發(fā)信息號(hào) 。我們向AutoResetEvent構(gòu)造方法傳入false,定義了這兩個(gè)實(shí)例初始狀態(tài)為unsignaled。這意味著我們?nèi)魏尉€程調(diào)用這兩個(gè)對(duì)象中的任何一個(gè) waitone方法將會(huì)被堵塞,直到我們調(diào)用了set方法。如果初試事件為true,那么autoresetEvent實(shí)例的狀態(tài)為sigaled,如果線程調(diào)用waitone方法則會(huì)立即處理。 然后事件狀態(tài)自動(dòng)變?yōu)閡nsignaled,所以需要再對(duì)改實(shí)例調(diào)用一次set方法,以便讓其他的線程對(duì)該實(shí)例調(diào)用waitone方法從而繼續(xù)執(zhí)行。 然后我們創(chuàng)建了第二個(gè)線程,其會(huì)執(zhí)行第一個(gè)操作10秒鐘,然后等待從第二個(gè)線程發(fā)出的信號(hào)。該信號(hào)意味著第一個(gè)操作已經(jīng)完成?,F(xiàn)在第二個(gè)線程在 等待主線程的信號(hào),我們對(duì)主線程做了一些1附加工作,并通過(guò)調(diào)用_mainEvent.Set方法發(fā)送了一個(gè)信號(hào)。然后等待從第二個(gè)線程發(fā)出的另一個(gè)信號(hào) AutoResetEvent類采用的是內(nèi)核時(shí)間模式,所以等待時(shí)間不能太長(zhǎng)。使用2.6節(jié)中的ManualResetEventslim類更好,因?yàn)樗褂玫氖腔旌夏J健?/p>
以上就是實(shí)例代碼講解c# 線程(下)的詳細(xì)內(nèi)容,更多關(guān)于c# 線程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#實(shí)現(xiàn)WinForm禁止最大化、最小化、雙擊標(biāo)題欄、雙擊圖標(biāo)等操作的方法
這篇文章主要介紹了C#實(shí)現(xiàn)WinForm禁止最大化、最小化、雙擊標(biāo)題欄、雙擊圖標(biāo)等操作的方法,涉及C#使用WinForm針對(duì)窗口操作的各種常用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08C# 連接SQL數(shù)據(jù)庫(kù)的方法及常用連接字符串
這篇文章主要介紹了C# 連接SQL數(shù)據(jù)庫(kù)的方法及常用連接字符串,有需要的朋友可以參考一下2014-01-01C#進(jìn)行文件讀寫(xiě)、創(chuàng)建、復(fù)制、移動(dòng)、刪除的方法
這篇文章主要介紹了C#進(jìn)行文件讀寫(xiě)、創(chuàng)建、復(fù)制、移動(dòng)、刪除的方法,涉及C#針對(duì)文件操作的常用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-03-03C#調(diào)用OpenCV開(kāi)發(fā)簡(jiǎn)易版美圖工具【推薦】
本文主要介紹在WPF項(xiàng)目中使用OpenCVSharp3-AnyCPU開(kāi)源類庫(kù)處理圖片,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2019-10-10C#基于Socket的TCP通信實(shí)現(xiàn)聊天室案例
這篇文章主要為大家詳細(xì)介紹了C#基于Socket的TCP通信實(shí)現(xiàn)聊天室案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02C#實(shí)現(xiàn)在底圖上動(dòng)態(tài)生成文字和圖片
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)在底圖上動(dòng)態(tài)生成文字和圖片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05