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

首頁 > 編程 > C# > 正文

C#多線程編程詳解

2019-10-29 21:18:57
字體:
來源:轉載
供稿:網友

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

一、使用線程的理由

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

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

3、可以使用線程來實現并發執行。

二、基本知識

1、進程與線程:進程作為操作系統執行程序的基本單位,擁有應用程序的資源,進程包含線程,進程的資源被線程共享,線程不擁有資源。

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

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

4、阻塞線程:Join,阻塞調用線程,直到該線程終止。

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

6、線程優先級:AboveNormal BelowNormal Highest Lowest Normal,默認為Normal。

三、線程的使用

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

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("不帶參數的線程函數");    }    public static void TestMethod(object data)    {      string datastr = data as string;      Console.WriteLine("帶參數的線程函數,參數為:{0}", datastr);    }  } }

四、線程池

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

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

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

五、Task類

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

構造一個Task<TResult>對象,并為泛型TResult參數傳遞一個操作的返回類型。

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;} //結果太大,拋出異常      return sum;    }  }}

一個任務完成時,自動啟動一個新任務。

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

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;} //結果溢出,拋出異常      return sum;    }  }}

六、委托異步執行

委托的異步調用: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");      //異步執行完成      string resultstr = mydelegate.EndInvoke(result);    }    //線程函數    public static string TestMethod(object data)    {      string datastr = data as string;      return datastr;    }    //異步回調函數    public static void TestCallback(IAsyncResult data)    {      Console.WriteLine(data.AsyncState);    }  }}

七、線程同步

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

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

3)Monitor實現線程同步

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

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

4)ReaderWriterLock

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

5)事件(Event)類實現同步

事件類有兩種狀態,終止狀態和非終止狀態,終止狀態時調用WaitOne可以請求成功,通過Set將時間狀態設置為終止狀態。

①AutoResetEvent(自動重置事件)

②ManualResetEvent(手動重置事件)

6)信號量(Semaphore)

信號量是由內核對象維護的int變量,為0時,線程阻塞,大于0時解除阻塞,當一個信號量上的等待線程解除阻塞后,信號量計數+1。

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

7)互斥體(Mutex)

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

 8)跨進程間的同步

通過設置同步對象的名稱就可以實現系統級的同步,不同應用程序通過同步對象的名稱識別不同同步對象。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 荣昌县| 瓮安县| 慈溪市| 葵青区| 吉林市| 五峰| 明溪县| 长葛市| 墨脱县| 石景山区| 福安市| 朔州市| 大方县| 万全县| 布拖县| 志丹县| 镇赉县| 临汾市| 宜章县| 泸水县| 大石桥市| 黔西县| 北票市| 怀集县| 星子县| 鹤壁市| 清徐县| 永寿县| 磐石市| 卓资县| 罗江县| 阜新市| 金山区| 沾益县| 晋中市| 武清区| 阿坝| 新余市| 遂溪县| 廊坊市| 繁昌县|