例項程式碼講解c# 執行緒(下)
前言
例項程式碼講解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(); } } } }
當主程式啟動時,定義了一個指定名稱的互斥量,設定initialowner標誌為false。這意味著如果互斥量已經被建立,則允許程式獲取該互斥量。如果沒有獲取到互斥量,程式則簡單的顯示running,的等待知道按下了任何鍵,然後釋放該互斥量並退出。 如果再運行同樣一個程式,則會在5秒內嘗試獲取互斥量。如果此時在第一個程式中按下了任何鍵,第二個程式則會開始執行。然而,如果保持等待5秒鐘,第二個程式將無法獲取到該互斥量。 該方式可用於在不同的程式中同步執行緒,可被推廣到大量的使用場景中。
使用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(); }
當主程式啟動時,建立了SemaphoreSlim的一個例項,並在其建構函式中指定允許的併發執行緒數量。然後啟動了6個不同名稱和不同初始執行時間的執行緒。每個執行緒都嘗試獲取資料庫的訪問,但是我們藉助於訊號系統限制了訪問資料庫的併發數為4個執行緒。當有4個執行緒獲取資料庫的訪問後,其他兩個執行緒需要等待,直到之前執行緒中的某一個完成工作並呼叫_semaphore.Release方法來發出訊號。
使用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!"); }
當主程式啟動時,定義了兩個autoresetEvent例項。其中一個是從子執行緒向主執行緒發訊號,另一個例項是從主執行緒向子執行緒發信息號 。我們向AutoResetEvent構造方法傳入false,定義了這兩個例項初始狀態為unsignaled。這意味著我們任何執行緒呼叫這兩個物件中的任何一個 waitone方法將會被堵塞,直到我們呼叫了set方法。如果初試事件為true,那麼autoresetEvent例項的狀態為sigaled,如果執行緒呼叫waitone方法則會立即處理。 然後事件狀態自動變為unsignaled,所以需要再對改例項呼叫一次set方法,以便讓其他的執行緒對該例項呼叫waitone方法從而繼續執行。 然後我們建立了第二個執行緒,其會執行第一個操作10秒鐘,然後等待從第二個執行緒發出的訊號。該訊號意味著第一個操作已經完成。現在第二個執行緒在 等待主執行緒的訊號,我們對主執行緒做了一些1附加工作,並通過呼叫_mainEvent.Set方法傳送了一個訊號。然後等待從第二個執行緒發出的另一個訊號 AutoResetEvent類採用的是核心時間模式,所以等待時間不能太長。使用2.6節中的ManualResetEventslim類更好,因為他使用的是混合模式。
以上就是例項程式碼講解c# 執行緒(下)的詳細內容,更多關於c# 執行緒的資料請關注我們其它相關文章!