1. 程式人生 > 程式設計 >例項程式碼講解c# 執行緒(下)

例項程式碼講解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# 執行緒的資料請關注我們其它相關文章!