C# 多執行緒併發程式設計資料彙總學習
阿新 • • 發佈:2019-02-01
多執行緒程式設計,非同步程式設計,都是感覺非常高大上的技術,在學習了無數前輩們的教學貼後,感覺還是無法融匯貫通,所以決定寫個彙總,整理了一下前輩們的程式碼,為了加強一遍理解。這裡一大堆複雜繁瑣和囉裡囉嗦的饒舌語法就不在重複了,直接上程式碼。
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);
}
}