歡迎您光臨本站 註冊首頁

實例代碼講解c# 線程(下)

←手機掃碼閱讀     niceskyabc @ 2020-06-26 , reply:0

前言

實例代碼講解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  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類更好,因為他使用的是混合模式。



[niceskyabc ] 實例代碼講解c# 線程(下)已經有272次圍觀

http://coctec.com/docs/c/language/show-post-239772.html