《C#多線程編程實現方式》

来源:http://www.cnblogs.com/likar/archive/2017/06/21/7058464.html
-Advertisement-
Play Games

一、使用線程的理由 1、可以使用線程將代碼同其他代碼隔離,提高應用程式的可靠性。 2、可以使用線程來簡化編碼。 3、可以使用線程來實現併發執行。 二、基本知識 1、進程與線程:進程作為操作系統執行程式的基本單位,擁有應用程式的資源,進程包含線程,進程的資源被線程共用,線程不擁有資源。 2、前臺線程和 ...


一、使用線程的理由

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將時間狀態設置為終止狀態。

    1)AutoResetEvent(自動重置事件)

    2)ManualResetEvent(手動重置事件)

  6)信號量(Semaphore)

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

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

  7)互斥體(Mutex)

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

   8)跨進程間的同步

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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Asp.Net.Identity為何物請自行搜索,也可轉向此文章http://www.cnblogs.com/shanyou/p/3918178.html 本來微軟已經幫我們將授權、認證以及資料庫存儲都一一處理好了。但是總有這種情況,如我們現在的項目是已經存在了資料庫,且庫里已經有用戶、角色等信息表 ...
  • using System; namespace DotNet.Utilities { /// <summary> /// BaseRandom /// 產生隨機數 /// /// 隨機數管理,最大值、最小值可以自己進行設定。 /// </summary> public class BaseRando ...
  • using System; namespace DotNet.Utilities { /// <summary> /// 時間類 /// 1、SecondToMinute(int Second) 把秒轉換成分鐘 /// </summary> public class TimeHelper { /// ...
  • using System.Text.RegularExpressions; namespace DotNet.Utilities { /// <summary> /// 漢字轉拼音類 /// </summary> public class EcanConvertToCh { //定義拼音區編碼數組 ...
  • 因為沒有AspNetCoreModule所以無法正常運行 http://download.microsoft.com/download/3/8/1/381CBBF3-36DA-4983-BFF3-5881548A70BE/DotNetCore.1.0.4_1.1.1-WindowsHosting.e ...
  • using System.Xml; using System.Data; namespace DotNet.Utilities { /// <summary> /// Xml的操作公共類 /// </summary> public class XmlHelper { #region 欄位定義 /// ...
  • https加密鏈接,在訪問的過程中,可以保護你的隱私,保證你的敏感數據不會被別人偷窺,竊取。如果你的伺服器在境外,使用https,可以有更穩定的訪問體驗。接下來我們看一下ZKEACMS如何配置使用HTTPS。 ...
  • using System; using System.Security.Cryptography; using System.Text; namespace DotNet.Utilities { /// <summary> /// Encrypt 的摘要說明。 /// </summary> publ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...