線程處理用於使程序可以執行併發處理,同時執行多個操做。C#中有三種線程的使用方法,BackgroundWorker組件、線程池、本身建立使用線程,接下來分別介紹如何使用。react
1.使用BackgroundWorker組件(建立多線程處理程序最可靠方法)安全
此類管理一個專用於處理指定方法的單獨線程。服務器
添加 DoWork 事件的事件處理程序,爲後臺操做作好準備,在此事件處理程序中調用耗時的操做。網絡
調用 RunWorkerAsync 函數,開始後臺操做。 多線程
處理 ProgressChanged 事件,收到進度更新的通知。 併發
處理RunWorkerCompleted 事件,在操做完成時收到通知。app
處理 ProgressChanged 和 RunWorkerCompleted 事件的方法能夠訪問應用程序的用戶界面,緣由是這兩個事件是在調用了 RunWorkerAsync 方法的線程上引起的。 可是,DoWork 事件處理程序沒法使用任何用戶界面對象,由於它在後臺線程上運行。異步
2.線程池,是能夠用來在後臺執行多個任務的線程集合,將任務添加到隊列,而後在建立線程後自動啓動這些任務。線程池一般用於服務器應用程序。 每一個傳入請求都將分配給線程池中的一個線程,所以能夠異步處理請求,而不會佔用主線程,也不會延遲後續請求的處理。一旦池中的某個線程完成任務,它將返回到等待線程隊列中,等待被再次使用,這種重用使應用程序能夠避免爲每一個任務建立新線程的開銷。線程池一般具備最大線程數限制。若是全部線程都繁忙,則額外的任務將放入隊列中,直到有線程可用時纔可以獲得處理。async
ThreadPool.QueueUserWorkItem(WaitCallback callBack)//將方法排入隊列以便執行。 ThreadPool.QueueUserWorkItem(WaitCallback callBack, object state)//將方法排入隊列以便執行,並指定包含該方法所用數據的對象。
3.建立和使用線程函數
若是須要對應用程序的線程的行爲進行更多的控制,則能夠本身管理線程。經過聲明類型爲 Thread 的變量,並調用爲要對新線程執行的過程或方法提供名稱的構造函數,從而建立一個新線程。
System.Threading.Thread newThread = new System.Threading.Thread(AMethod);
線程其餘知識點:
1.前臺/後臺線程
後臺線程與前臺線程徹底同樣,只是後臺線程不會阻止進程終止。前臺線程的運行時間不限定,然後臺線程則在最後一個前臺線程中止時當即中止。 可使用 IsBackground 屬性肯定或更改線程的後臺狀態。默認狀況下,主線程、經過Thread類構造函數建立的線程在前臺執行,線程池線程、從非託管代碼進入托管環境的線程在後臺執行。
2.線程的參數和返回值
爲線程提供參數:將目標方法包裹在類中,併爲該類定義字段,這些字段將被用做新線程的參數。
從線程獲取返回值:使用BackgroundWorker 組件來管理線程,在任務完成時引起RunWorkerCompleted 事件,而後用事件處理程序處理結果。
3.線程同步
在應用程序中使用多個線程,必須協調對資源(如文件句柄、網絡鏈接和內存)的訪問。C#中的線程同步方法有鎖、監視器、同步事件和等待句柄、Mutex對象、Interlocked類、ReaderWriter鎖。
鎖:lock 關鍵字將語句塊標記爲臨界區,方法是獲取給定對象的互斥鎖,執行語句,而後釋放該鎖。
監視器:與lock關鍵字相似,防止多個線程同時執行代碼塊,可是lock更簡潔、更安全。
同步事件和等待句柄:同步事件有終止、非終止兩個狀態的對象,用來激活和掛起線程,讓線程等待一個非終止同步事件能夠將線程掛起,將事件狀態變爲終止能夠激活線程。若是線程嘗試等待已經終止的事件,則線程繼續執行,不會受到延遲。同步事件有AutoResetEvent和ManualResetEvent兩種,只要AutoResetEvent 激活線程,其狀態自動從終止變爲非終止,ManualResetEvent 容許它的終止狀態激活任意個線程,並只有調用其Reset方法時才還原到非終止狀態。
經過調用WaitOne、WaitAny、WaitAll等待方法使線程等待事件,當調用事件的Set方法,事件變爲終止狀態。
using System; using System.Threading; class ThreadingExample { static AutoResetEvent autoEvent; static void DoWork() { Console.WriteLine(" worker thread started, now waiting on event..."); autoEvent.WaitOne(); Console.WriteLine(" worker thread reactivated, now exiting..."); } static void Main() { autoEvent = new AutoResetEvent(false); Console.WriteLine("main thread starting worker thread..."); Thread t = new Thread(DoWork); t.Start(); Console.WriteLine("main thread sleeping for 1 second..."); Thread.Sleep(1000); Console.WriteLine("main thread signaling worker thread..."); autoEvent.Set();
Console.ReadLine(); } }
執行結果
Mutex 對象,與監視器相似。
Interlock類,使用 Interlocked 類的方法來避免在多個線程嘗試同時更新或比較同一個值時可能出現的問題。使用這個類的方法能夠安全地遞增、遞減、交換和比較任何線程中的值。
ReadWriter鎖,只在寫入數據時鎖定資源,在不更新數據時容許多個客戶端同時讀取數據。 ReaderWriterLock 類在線程修改資源時將強制其獨佔訪問資源,但在讀取資源時則容許非獨佔訪問。ReaderWriterLock 類定義支持單個寫線程和多個讀線程的鎖。
死鎖,多線程應用程序始終存在deadlock 的危險,在編碼前多考慮,避免死鎖。
4.線程計時器。System.Threading.Timer 類可用於按期在單獨的線程上運行任務,建立實例後計時器開始啓動。