国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C#多線程編程詳解

2020-01-24 00:56:12
字體:
供稿:網(wǎng)友

C#提供了豐富的多線程操作,為編程帶來了極大的便利。

一、使用線程的理由

1、可以使用線程將代碼同其他代碼隔離,提高應(yīng)用程序的可靠性。

2、可以使用線程來簡化編碼。

3、可以使用線程來實現(xiàn)并發(fā)執(zhí)行。

二、基本知識

1、進(jìn)程與線程:進(jìn)程作為操作系統(tǒng)執(zhí)行程序的基本單位,擁有應(yīng)用程序的資源,進(jìn)程包含線程,進(jìn)程的資源被線程共享,線程不擁有資源。

2、前臺線程和后臺線程:通過Thread類新建線程默認(rèn)為前臺線程。當(dāng)所有前臺線程關(guān)閉時,所有的后臺線程也會被直接終止,不會拋出異常。

3、掛起(Suspend)和喚醒(Resume):由于線程的執(zhí)行順序和程序的執(zhí)行情況不可預(yù)知,所以使用掛起和喚醒容易發(fā)生死鎖的情況,在實際應(yīng)用中應(yīng)該盡量少用。

4、阻塞線程:Join,阻塞調(diào)用線程,直到該線程終止。

5、終止線程:Abort:拋出 ThreadAbortException 異常讓線程終止,終止后的線程不可喚醒。Interrupt:拋出 ThreadInterruptException 異常讓線程終止,通過捕獲異常可以繼續(xù)執(zhí)行。

6、線程優(yōu)先級:AboveNormal BelowNormal Highest Lowest Normal,默認(rèn)為Normal。

三、線程的使用

線程函數(shù)通過委托傳遞,可以不帶參數(shù),也可以帶參數(shù)(只能有一個參數(shù)),可以用一個類或結(jié)構(gòu)體封裝參數(shù)。

namespace Test{  class Program  {    static void Main(string[] args)    {      Thread t1 = new Thread(new ThreadStart(TestMethod));      Thread t2 = new Thread(new ParameterizedThreadStart(TestMethod));      t1.IsBackground = true;      t2.IsBackground = true;      t1.Start();      t2.Start("hello");      Console.ReadKey();    }    public static void TestMethod()    {      Console.WriteLine("不帶參數(shù)的線程函數(shù)");    }    public static void TestMethod(object data)    {      string datastr = data as string;      Console.WriteLine("帶參數(shù)的線程函數(shù),參數(shù)為:{0}", datastr);    }  } }

四、線程池

由于線程的創(chuàng)建和銷毀需要耗費一定的開銷,過多的使用線程會造成內(nèi)存資源的浪費,出于對性能的考慮,于是引入了線程池的概念。線程池維護一個請求隊列,線程池的代碼從隊列提取任務(wù),然后委派給線程池的一個線程執(zhí)行,線程執(zhí)行完不會被立即銷毀,這樣既可以在后臺執(zhí)行任務(wù),又可以減少線程創(chuàng)建和銷毀所帶來的開銷。

線程池線程默認(rèn)為后臺線程(IsBackground)。

namespace Test{  class Program  {    static void Main(string[] args)    {      //將工作項加入到線程池隊列中,這里可以傳遞一個線程參數(shù)      ThreadPool.QueueUserWorkItem(TestMethod, "Hello");      Console.ReadKey();    }    public static void TestMethod(object data)    {      string datastr = data as string;      Console.WriteLine(datastr);    }  }}

五、Task類

使用ThreadPool的QueueUserWorkItem()方法發(fā)起一次異步的線程執(zhí)行很簡單,但是該方法最大的問題是沒有一個內(nèi)建的機制讓你知道操作什么時候完成,有沒有一個內(nèi)建的機制在操作完成后獲得一個返回值。為此,可以使用System.Threading.Tasks中的Task類。

構(gòu)造一個Task<TResult>對象,并為泛型TResult參數(shù)傳遞一個操作的返回類型。

namespace Test{  class Program  {    static void Main(string[] args)    {      Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000);      t.Start();      t.Wait();      Console.WriteLine(t.Result);      Console.ReadKey();    }    private static Int32 Sum(Int32 n)    {      Int32 sum = 0;      for (; n > 0; --n)        checked{ sum += n;} //結(jié)果太大,拋出異常      return sum;    }  }}

一個任務(wù)完成時,自動啟動一個新任務(wù)。

一個任務(wù)完成后,它可以啟動另一個任務(wù),下面重寫了前面的代碼,不阻塞任何線程。

namespace Test{  class Program  {    static void Main(string[] args)    {      Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000);      t.Start();      //t.Wait();      Task cwt = t.ContinueWith(task => Console.WriteLine("The result is {0}",t.Result));      Console.ReadKey();    }    private static Int32 Sum(Int32 n)    {      Int32 sum = 0;      for (; n > 0; --n)        checked{ sum += n;} //結(jié)果溢出,拋出異常      return sum;    }  }}

六、委托異步執(zhí)行

委托的異步調(diào)用:BeginInvoke() 和 EndInvoke()

namespace Test{  public delegate string MyDelegate(object data);  class Program  {    static void Main(string[] args)    {      MyDelegate mydelegate = new MyDelegate(TestMethod);      IAsyncResult result = mydelegate.BeginInvoke("Thread Param", TestCallback, "Callback Param");      //異步執(zhí)行完成      string resultstr = mydelegate.EndInvoke(result);    }    //線程函數(shù)    public static string TestMethod(object data)    {      string datastr = data as string;      return datastr;    }    //異步回調(diào)函數(shù)    public static void TestCallback(IAsyncResult data)    {      Console.WriteLine(data.AsyncState);    }  }}

七、線程同步

1)原子操作(Interlocked):所有方法都是執(zhí)行一次原子讀取或一次寫入操作。

2)lock()語句:避免鎖定public類型,否則實例將超出代碼控制的范圍,定義private對象來鎖定。

3)Monitor實現(xiàn)線程同步

通過Monitor.Enter() 和 Monitor.Exit()實現(xiàn)排它鎖的獲取和釋放,獲取之后獨占資源,不允許其他線程訪問。

還有一個TryEnter方法,請求不到資源時不會阻塞等待,可以設(shè)置超時時間,獲取不到直接返回false。

4)ReaderWriterLock

當(dāng)對資源操作讀多寫少的時候,為了提高資源的利用率,讓讀操作鎖為共享鎖,多個線程可以并發(fā)讀取資源,而寫操作為獨占鎖,只允許一個線程操作。

5)事件(Event)類實現(xiàn)同步

事件類有兩種狀態(tài),終止?fàn)顟B(tài)和非終止?fàn)顟B(tài),終止?fàn)顟B(tài)時調(diào)用WaitOne可以請求成功,通過Set將時間狀態(tài)設(shè)置為終止?fàn)顟B(tài)。

①AutoResetEvent(自動重置事件)

②ManualResetEvent(手動重置事件)

6)信號量(Semaphore)

信號量是由內(nèi)核對象維護的int變量,為0時,線程阻塞,大于0時解除阻塞,當(dāng)一個信號量上的等待線程解除阻塞后,信號量計數(shù)+1。

線程通過WaitOne將信號量減1,通過Release將信號量加1,使用很簡單。

7)互斥體(Mutex)

獨占資源,用法與Semaphore相似。

 8)跨進(jìn)程間的同步

通過設(shè)置同步對象的名稱就可以實現(xiàn)系統(tǒng)級的同步,不同應(yīng)用程序通過同步對象的名稱識別不同同步對象。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 修武县| 青岛市| 揭阳市| 宁陕县| 夹江县| 蒙山县| 凤城市| 桦南县| 门头沟区| 麻阳| 通海县| 无棣县| 民勤县| 凌源市| 渝北区| 张北县| 兴文县| 安宁市| 台中县| 望江县| 平远县| 台山市| 揭西县| 顺昌县| 调兵山市| 黄骅市| 平昌县| 汉源县| 永吉县| 托克逊县| 繁昌县| 印江| 浮梁县| 美姑县| 新宾| 尚志市| 昌图县| 商南县| 桃源县| 新化县| 枣庄市|