1. 程式人生 > >C#多執行緒程式設計

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引數傳遞一個操作的返回型別。

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)跨程序間的同步

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

———————————————轉—————————————-
作者:阿凡盧
出處:http://www.cnblogs.com/luxiaoxun/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。

相關推薦

理解c++執行程式設計

多執行緒程式設計 本篇博文不是主要介紹互斥鎖之類的,是理解執行緒的執行,以便以後有把握的寫多執行緒程式。 #include<thread> #include<iostream&g

Linux c執行程式設計的4個例項

在主流的作業系統中,多工一般都提供了程序和執行緒兩種實現方式,程序享有獨立的程序空間,而執行緒相對於程序來說是一種更加輕量級的多工並行,多執行緒之間一般都是共享所在程序的記憶體空間的。   Linux也不例外,雖然從核心的角度來看,執行緒體現為一種對程序的"克隆"(clon

C#執行程式設計筆記(5.2)-在lambda表示式中使用await操作符

近來在學習Eugene Agafonov編寫的《C#多執行緒程式設計實戰》(譯),做些筆記也順便分享一下^-^using System; using System.Threading.Tasks; using System.Threading; namespace 在Lam

Linux C 執行程式設計總結

執行緒的資料處理   和程序相比,執行緒的最大優點之一是資料的共享性,各個程序共享父程序處沿襲的資料段,可以方便的獲得、修改資料。但這也給多執行緒程式設計帶來了許多問題。我們必須當心有多個不同的程序訪問相同的變數。許多函式是不可重入的,即同時不能執行一個函式的多個拷貝(除非使用不同的資料段)。在函式中宣告的

C++執行程式設計學習(1)】-CPU個數、CPU核心數、CPU執行

轉自:CPU個數、CPU核心數、CPU執行緒數(by kimsimple)   CPU個數即CPU晶片個數。 CPU核心數是指物理上,也就是硬體上存在著幾個核心。比如,雙核就是包括2個相對獨立的CPU核心單元組,四核就包含4個相對獨立的CPU核心單元組。 CPU執行緒數是一

【Linux C 執行程式設計】互斥鎖與條件變數

一、互斥鎖互斥量從本質上說就是一把鎖, 提供對共享資源的保護訪問。  1. 初始化:  在Linux下, 執行緒的互斥量資料型別是pthread_mutex_t. 在使用前, 要對它進行初始化:  對於靜態分配的互斥量, 可以把它設定為PTHREAD_MUTEX_INITIA

樹莓派3B Linux下C++執行程式設計

下面的程式碼手動建立了兩個執行緒,一個執行緒是讀取串列埠的資料,另一個執行緒是通過UDP來讀取網路通訊收到的資料。加上main函式的執行緒,一共三個執行緒。 先簡單講一下多執行緒的建立, pthread_t serial; int ser =

C++——執行程式設計(二)std::mutex 執行同步、解決資源競爭問題

前言 執行緒同步 這裡的“同”不是同時、一起執行的意思,而是指協同、協助、互相配合。執行緒同步是指多個執行緒協同步調,按預定的先後次序進行執行。 執行緒A和B一塊配合,A執行到一定程度時要依靠B的某個結果,於是停下來,示意B執行;B依言執行,再將結果給A;

windows C++執行程式設計高階篇 實現執行同步

    上一篇文章windows程式設計 使用C++實現多執行緒類僅僅是介紹了怎樣用類來實現多執行緒,這篇文章則重點介紹多執行緒中資料同步的問題。好了,廢話不多說,進入主題。     問題場景:這裡我們假設有這樣一個工作流水線(CWorkPipeline),它不斷的生成一

c# multi thread programming ,c# 執行程式設計

使用函式代表(委託)的BeginInvoke()和EndInvoke()方法。可以在新開的執行緒上執行函式,並且在主執行緒得到函式的返回值。 using System; using System.Threading; namespace MultiThread { pub

C#執行程式設計筆記(5.5)-處理非同步操作中的異常

近來在學習Eugene Agafonov編寫的《C#多執行緒程式設計實戰》(譯),做些筆記也順便分享一下^-^本篇將描述在C#中使用非同步函式時如何處理異常。我們將學習對多個並行的非同步操作使用await時如何聚合異常。using System; using System.T

Linux C++執行程式設計

1.介紹   相比程序,多執行緒是一種節儉的多工操作方式。在Linux系統下,啟動一個新的程序必須分配給它獨立的地址空間,建立眾多的資料表來維護它的程式碼段、堆疊段和資料段。而執行一個程序中的多個執行緒,它們彼此之間使用相同的地址空間,共享大部分資料,啟動一個

C#執行程式設計筆記(2.5)-使用CountDownEvent類

近來在學習Eugene Agafonov編寫的《C#多執行緒程式設計實戰》(譯),做些筆記也順便分享一下^-^using System; using System.Threading; namespace CountDownEvent_Test { class Pr

C#執行程式設計

一、使用執行緒的理由 1、可以使用執行緒將程式碼同其他程式碼隔離,提高應用程式的可靠性。 2、可以使用執行緒來簡化編碼。 3、可以使用執行緒來實現併發執行。 二、基本知識 1、程序與執行緒:程序作為作業系統執行程式的基本單位,擁有應用程式的資源,程序包

C#執行程式設計筆記(2.7)-使用ReaderWriterLockSlim類

近來在學習Eugene Agafonov編寫的《C#多執行緒程式設計實戰》(譯),做些筆記也順便分享一下^-^using System; using System.Collections.Generic; using System.Threading; namespace

C#執行程式設計筆記(2.1)-使用Mutex類

近來在學習Eugene Agafonov編寫的《C#多執行緒程式設計實戰》(譯),做些筆記也順便分享一下^-^Mutex是一種原始的同步方法,其只對一個執行緒授予對共享資源的獨佔訪問using System; using System.Threading; namespac

c++ 執行程式設計入門 訊號量使用

1、pthread_create函式定義 int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void *(*start_rtn)(void), void

C#執行程式設計筆記(1.2)-檢測執行狀態State

近來在學習Eugene Agafonov編寫的《C#多執行緒程式設計實戰》(譯),做些筆記也順便分享一下^-^using System; using System.Threading; namespace 檢測執行緒狀態 { class Program {

C++執行程式設計除錯技巧

__builtin_return_address():此函式返回當前函式或其呼叫函式的返回地址 __builtin_frame_address():返回呼叫函式的幀地址 void *stack[4]; _stack[0] = __builtin_return_address(1); if (__builti

ubuntu下C++執行程式設計(cmake生成makefile)

最近做專案要用到多執行緒的程式設計,又要用到opencv因此採用cmake生成makefile然後進行編譯的方法比較簡單。這裡給出多執行緒的簡單例項。 主函式非常簡單: #include <iostream> #include <pthread.h&g