1. 程式人生 > >C# 多執行緒併發程式設計資料彙總學習

C# 多執行緒併發程式設計資料彙總學習

多執行緒程式設計,非同步程式設計,都是感覺非常高大上的技術,在學習了無數前輩們的教學貼後,感覺還是無法融匯貫通,所以決定寫個彙總,整理了一下前輩們的程式碼,為了加強一遍理解。這裡一大堆複雜繁瑣和囉裡囉嗦的饒舌語法就不在重複了,直接上程式碼。

class Program
{
    static void Main(string[] args)
    {
        #region 通過Thread顯示當前執行緒資訊
        Thread thread0 = Thread.CurrentThread;
        thread0.Name = "Main Thread";
        string
threadMessage = string.Format("Thread ID:{0}\n Current AppDomainId:{1}\n " +"Current ContextId:{2}\n Thread Name:{3}\n" +"Thread State:{4}\n Thread Priority:{5}\n",thread0.ManagedThreadId, Thread.GetDomainID(),Thread.CurrentContext.ContextID, thread0.Name, thread0.ThreadState, thread0.Priority); Console.WriteLine(threadMessage); #endregion
#region 使用ThreadStart委託 Console.WriteLine("Main threadId is:" + Thread.CurrentThread.ManagedThreadId); Thread thread1 = new Thread(new ThreadStart(ShowMessage)); thread1.Start(); Console.WriteLine("Do something ..........!"); Console.WriteLine("Main thread working is complete!"
); #endregion #region 使用ParameterizedThreadStart委託 Console.WriteLine("Main threadId is:" + Thread.CurrentThread.ManagedThreadId); //繫結帶引數的非同步方法 Thread thread2 = new Thread(new ParameterizedThreadStart(ShowMessage)); Person person = new Person(); person.Name = "Jack"; person.Age = 21; thread2.Start(person); //啟動非同步執行緒 Console.WriteLine("Do something ..........!"); Console.WriteLine("Main thread working is complete!"); #endregion #region 前臺執行緒與後臺執行緒 /* 使用Thread.Start()啟動的執行緒預設為前臺執行緒,而系統必須等待所有前臺執行緒執行結束後, 應用程式域才會自動解除安裝。執行緒Thread有一個屬性IsBackground,通過把此屬性設定為true, 就可以把執行緒設定為後臺執行緒!這時應用程式域將在主執行緒完成時就被解除安裝,而不會等待非同步執行緒的執行。 */ Thread thread3 = new Thread(new ThreadStart(ShowMessage)); thread3.IsBackground = true; thread3.Start(); #endregion #region 終止執行緒 Thread thread4 = new Thread(new ThreadStart(AsyncThread)); thread4.IsBackground = true; thread4.Start(); thread4.Join(); #endregion /* CLR執行緒池分為工作者執行緒(workerThreads)與I/O執行緒 (completionPortThreads) 兩種, 工作者執行緒是主要用作管理CLR內部物件的運作,I/O(Input/Output) 執行緒顧名思義是用於與 外部系統交換資訊。通過***ThreadPool.GetMax(out int workerThreads,out int completionPortThreads )和 ThreadPool.SetMax( int workerThreads, int completionPortThreads)兩個方法可以分別讀取和設定CLR執行緒池中工作者執行緒與I/O執行緒的最大執行緒數。 在Framework2.0中最大執行緒預設為25*CPU數,在Framewok3.0、4.0中最大執行緒數預設為250*CPU數, 在近年 I3,I5,I7 CPU出現後,執行緒池的最大值一般預設為1000、2000。 若想測試執行緒池中有多少的執行緒正在投入使用, 可以通過ThreadPool.GetAvailableThreads( out int workerThreads,out int completionPortThreads ) 方法。 使用CLR執行緒池的工作者執行緒一般有兩種方式,一是直接通過 ThreadPool.QueueUserWorkItem() 方法,二是通過委託 */ #region 通過QueueUserWorkItem啟動工作者執行緒 //把CLR執行緒池的最大值設定為1000 ThreadPool.SetMaxThreads(1000, 1000); //顯示主執行緒啟動時執行緒池資訊 ThreadMessage("Start"); //啟動工作者執行緒 ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncCallback1)); ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncCallback2), "Hello Elva"); #endregion /* 通過委託類實現執行緒池這種方法是在太噁心了,如果不瞭解原理生搬硬套,很容易走形式,而且記不住, 甚是麻煩,建議大家好好看看微軟的底層框架,為啥微軟會將這種方法做的如此難以理解, 我想肯定是微軟將此方法封裝的太深造成的。 */ #region 利用BeginInvoke與EndInvoke完成非同步委託方法 ThreadMessage("Main Thread"); //建立委託 MyDelegate myDelegate0 = new MyDelegate(Hello); //非同步呼叫委託,獲取計算結果 IAsyncResult result0 = myDelegate0.BeginInvoke("Leslie", null, null); //完成主執行緒其他工作 Console.WriteLine("............."); //等待非同步方法完成,呼叫EndInvoke(IAsyncResult)獲取執行結果 string data0 = myDelegate0.EndInvoke(result0); Console.WriteLine(data0); #endregion #region 輪詢方式 ThreadMessage("Main Thread"); //建立委託 MyDelegate myDelegate1 = new MyDelegate(Hello); //非同步呼叫委託,獲取計算結果 IAsyncResult result1 = myDelegate1.BeginInvoke("Leslie", null, null); //在非同步執行緒未完成前執行其他工作 while (!result1.IsCompleted) { Thread.Sleep(200); Console.WriteLine("Main thead do work!"); } while (!result1.AsyncWaitHandle.WaitOne(200)) { Console.WriteLine("Main thead do work!"); } string data1 = myDelegate1.EndInvoke(result1); Console.WriteLine(data1); #endregion #region 監視多個執行物件 ThreadMessage("Main Thread"); //建立委託 MyDelegate myDelegate2 = new MyDelegate(Hello); //非同步呼叫委託,獲取計算結果 IAsyncResult result2 = myDelegate2.BeginInvoke("Leslie", null, null); //此處可加入多個檢測物件 WaitHandle[] waitHandleList = new WaitHandle[] { result2.AsyncWaitHandle }; while (!WaitHandle.WaitAll(waitHandleList, 200)) { Console.WriteLine("Main thead do work!"); } string data2 = myDelegate2.EndInvoke(result2); Console.WriteLine(data2); #endregion /* 這種回撥函式的方式代替了輪詢的方式,但更是難以理解,只能機械的跟套公式一樣的運用, 那麼你跟不會多執行緒的人沒有任何區別。但是如果你理解了底層的框架實現原理,相信就會清晰多了, 我這個小菜暫時只能看看怎麼用,慚愧。 */ #region 回撥函式 ThreadMessage("Main Thread"); //建立委託 MyDelegate myDelegate3 = new MyDelegate(Hello); //非同步呼叫委託,獲取計算結果 myDelegate3.BeginInvoke("Leslie", new AsyncCallback(Completed), null); //建立Person物件 Person person3 = new Person(); person3.Name = "Elva"; person3.Age = 27; //非同步呼叫委託,輸入引數物件person, 獲取計算結果 myDelegate3.BeginInvoke("Leslie", new AsyncCallback(Completed3), person); //在啟動非同步執行緒後,主執行緒可以繼續工作而不需要等待 for (int n = 0; n < 6; n++) { Console.WriteLine(" Main thread do work!"); } Console.WriteLine(""); #endregion } //展示程序資訊 public static void ShowMessage() { string message = string.Format("Async threadId is :{0}",Thread.CurrentThread.ManagedThreadId); Console.WriteLine(message); for (int n = 0; n < 10; n++) { Thread.Sleep(300); Console.WriteLine("The number is:" + n.ToString()); } } public class Person { public string Name{ get;set;} public int Age { get;set;} } public static void ShowMessage(object person) { if (person != null) { Person _person = (Person)person; string message = string.Format("\n{0}'s age is {1}!\nAsync threadId is:{2}",_person.Name, _person.Age, Thread.CurrentThread.ManagedThreadId); Console.WriteLine(message); } for (int n = 0; n < 10; n++) { Thread.Sleep(300); Console.WriteLine("The number is:" + n.ToString()); } } //以非同步方式呼叫 static void AsyncThread() { try { string message = string.Format("\nAsync threadId is:{0}", Thread.CurrentThread.ManagedThreadId); Console.WriteLine(message); for (int n = 0; n < 10; n++) { //當n等於4時,終止執行緒 if (n >= 4) { Thread.CurrentThread.Abort(n); } Thread.Sleep(300); Console.WriteLine("The number is:" + n.ToString()); } } catch (ThreadAbortException ex) { //輸出終止執行緒時n的值 if (ex.ExceptionState != null) Console.WriteLine(string.Format("Thread abort when the number is: {0}!", ex.ExceptionState.ToString())); //取消終止,繼續執行執行緒 Thread.ResetAbort(); Console.WriteLine("Thread ResetAbort!"); } //執行緒結束 Console.WriteLine("Thread Close!"); } static void AsyncCallback1(object state) { Thread.Sleep(200); ThreadMessage("AsyncCallback"); Console.WriteLine("Async thread do work!"); } static void AsyncCallback2(object state) { Thread.Sleep(200); ThreadMessage("AsyncCallback"); string data = (string)state; Console.WriteLine("Async thread do work!\n" + data); } //顯示執行緒現狀 static void ThreadMessage(string data) { string message = string.Format("{0}\n CurrentThreadId is {1}", data, Thread.CurrentThread.ManagedThreadId); Console.WriteLine(message); } delegate string MyDelegate(string name); static string Hello(string name) { ThreadMessage("Async Thread"); Thread.Sleep(2000); return "Hello " + name; } static void Completed(IAsyncResult result) { ThreadMessage("Async Completed"); //獲取委託物件,呼叫EndInvoke方法獲取執行結果 AsyncResult _result = (AsyncResult)result; MyDelegate myDelegate = (MyDelegate)_result.AsyncDelegate; string data = myDelegate.EndInvoke(_result); Console.WriteLine(data); } static void Completed3(IAsyncResult result) { ThreadMessage("Async Completed"); //獲取委託物件,呼叫EndInvoke方法獲取執行結果 AsyncResult _result = (AsyncResult)result; MyDelegate myDelegate = (MyDelegate)_result.AsyncDelegate; string data = myDelegate.EndInvoke(_result); //獲取Person物件 Person person = (Person)result.AsyncState; string message = person.Name + "'s age is " + person.Age.ToString(); Console.WriteLine(data + "\n" + message); } }