實例代碼講解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();
}
}
}
}
當主程序啟動時,定義了一個指定名稱的互斥量,設(shè)置initialowner標志為false。這意味著如果互斥量已經(jīng)被創(chuàng)建,則允許程序獲取該互斥量。如果沒有獲取到互斥量,程序則簡單的顯示running,的等待知道按下了任何鍵,然后釋放該互斥量并退出。 如果再運行同樣一個程序,則會在5秒內(nèi)嘗試獲取互斥量。如果此時在第一個程序中按下了任何鍵,第二個程序則會開始執(zhí)行。然而,如果保持等待5秒鐘,第二個程序?qū)o法獲取到該互斥量。 該方式可用于在不同的程序中同步線程,可被推廣到大量的使用場景中。
使用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();
}
當主程序啟動時,創(chuàng)建了SemaphoreSlim的一個實例,并在其構(gòu)造函數(shù)中指定允許的并發(fā)線程數(shù)量。然后啟動了6個不同名稱和不同初始運行時間的線程。每個線程都嘗試獲取數(shù)據(jù)庫的訪問,但是我們借助于信號系統(tǒng)限制了訪問數(shù)據(jù)庫的并發(fā)數(shù)為4個線程。當有4個線程獲取數(shù)據(jù)庫的訪問后,其他兩個線程需要等待,直到之前線程中的某一個完成工作并調(diào)用_semaphore.Release方法來發(fā)出信號。
使用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實例。其中一個是從子線程向主線程發(fā)信號,另一個實例是從主線程向子線程發(fā)信息號 。我們向AutoResetEvent構(gòu)造方法傳入false,定義了這兩個實例初始狀態(tài)為unsignaled。這意味著我們?nèi)魏尉€程調(diào)用這兩個對象中的任何一個 waitone方法將會被堵塞,直到我們調(diào)用了set方法。如果初試事件為true,那么autoresetEvent實例的狀態(tài)為sigaled,如果線程調(diào)用waitone方法則會立即處理。 然后事件狀態(tài)自動變?yōu)閡nsignaled,所以需要再對改實例調(diào)用一次set方法,以便讓其他的線程對該實例調(diào)用waitone方法從而繼續(xù)執(zhí)行。 然后我們創(chuàng)建了第二個線程,其會執(zhí)行第一個操作10秒鐘,然后等待從第二個線程發(fā)出的信號。該信號意味著第一個操作已經(jīng)完成?,F(xiàn)在第二個線程在 等待主線程的信號,我們對主線程做了一些1附加工作,并通過調(diào)用_mainEvent.Set方法發(fā)送了一個信號。然后等待從第二個線程發(fā)出的另一個信號 AutoResetEvent類采用的是內(nèi)核時間模式,所以等待時間不能太長。使用2.6節(jié)中的ManualResetEventslim類更好,因為他使用的是混合模式。
以上就是實例代碼講解c# 線程(下)的詳細內(nèi)容,更多關(guān)于c# 線程的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
c#解析jobject的數(shù)據(jù)結(jié)構(gòu)
這篇文章介紹了c#解析jobject數(shù)據(jù)結(jié)構(gòu)的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07

