一.CLR線程池並不會在CLR初始化時立即建立線程,而是在應用程序要創建線程來運行任務時,線程池才初始化一個線程。

 //通過CLR線程池所建立的線程總是默認為後台線程,優先級數為ThreadPriority.Normal。

1.線程池初始化時是沒有線程的,線程池裏的線程的初始化與其他線程一樣,但是在完成任務以後,該線程不會自行銷燬,而是以掛起的狀態返回到線程池。

2.直到應用程序再次向線程池發出請求時,線程池裏掛起的線程就會再度激活執行任務。

3.這樣既節省了建立線程所造成的性能損耗,也可以讓多個任務反覆重用同一線程,從而在應用程序生存期內節約大量開銷。

二.CLR線程池分為工作者線程(workerThreads)與I/O線程(completionPortThreads)兩種:

1.工作者線程是主要用作管理CLR內部對象的運作,通常用於計算密集的任務。

2.I/O(Input/Output)線程主要用於與外部系統交互信息,如輸入輸出,CPU僅需在任務開始的時候,將任務的參數傳遞給設備,然後啓動硬件設備即可。

三.使用CLR線程池的工作者線程一般有兩種方式:

1.通過ThreadPool.QueueUserWorkItem()方法;

(1)ThreadPool線程池中有兩個重載的靜態方法可以直接啓動工作者線程:

ThreadPool.QueueUserWorkItem(WaitCallback(方法名));

//啓動工作者線程(無參數)
 ThreadPool.QueueUserWorkItem(new WaitCallback(RunMyMethod));

ThreadPool.QueueUserWorkItem(new WaitCallback(方法名),Object對象參數);

使用第二個重載方法ThreadPool.QueueUserWorkItem(WaitCallback,object)方法可以把object對象作為參數傳送到回調函數中。

//啓動工作者線程(有參數 obj類型)
 ThreadPool.QueueUserWorkItem(new WaitCallback(MyMethod), Obj);
 void MyMethod(object Obj){//..}

WaitCallback委託指向的必須是一個帶有object參數的無返回值方法,傳遞多個參數只有通過委託

2.通過委託;

使用BeginInvoke與EndInvoke委託異步調用線程

建立一個委託對象,通過IAsyncResult BeginInvoke(string name,AsyncCallback callback,object state)異步調用委託方法,BeginInvoke方法除最後的兩個參數外,其他參數都是與方法參數相對應的。

利用EndInvoke(IAsyncResult--上一步BeginInvoke返回的對象)方法就可以結束異步操作,獲取委託的運行結果。

//聲明委託
//delegate string MyDelegate(string Name,int Age);
//建立委託
MyDelegate myDelegate = new MyDelegate(GetInfo);
//異步調用委託,除最後兩個參數外,前面的參數都可以傳進去
IAsyncResult result = myDelegate.BeginInvoke("小明",18, null, null);  //IAsynResult還能輪詢判斷
//調用EndInvoke(IAsyncResult)獲取運行結果
string data = myDelegate.EndInvoke(result);
//調用的方法
private string GetInfo(string Name,int Age)
{
   return string.Format("我是{0},今年{1}歲!",name,age);
}
要注意的是並不知道異步操作什麼時候執行完,什麼時候開始調用EndInvoke,因為一旦EndInvoke主線程就會處於阻塞等待狀態。這時需要用到IAsyncResult提高主線程的工作性能
//IAsyncResult屬性
public interface IAsyncResult
{
  object AsyncState {get;}       //獲取用户定義的對象,它限定或包含關於異步操作的信息。
  WailHandle AsyncWaitHandle {get;}  //獲取用於等待異步操作完成的 WaitHandle。
  bool CompletedSynchronously {get;} //獲取異步操作是否同步完成的指示。
  bool IsCompleted {get;}        //獲取異步操作是否已完成的指示。
}
//利用IsCompleted屬性,來判斷異步線程是否完成
while (!result.IsCompleted)
{
      Thread.Sleep(500);          
      Console.WriteLine("異步線程還沒完成,主線程幹其他事!");
 }
//除了IsCompleted屬性外,還可以使用AsyncWaitHandle如下3個方法實現同樣輪詢判斷效果
//WaitOne:判斷單個異步線程是否完成;
//WaitAny:判斷是否異步線程是否有指定數量個已完成;
//WaitAll:判斷是否所有的異步線程已完成;
//WaitOne:
 //比上個例子,判斷條件由IsCompleted屬性換成了AsyncWaitHandle,僅此而已
  while (!result.AsyncWaitHandle.WaitOne(200))
  {
      Console.WriteLine("異步線程沒完,主線程繼續幹活!");
  }
//WaitAny:
 //是否完成了指定數量
  WaitHandle[] waitHandleList = new WaitHandle[] { result.AsyncWaitHandle };
  while (WaitHandle.WaitAny(waitHandleList, 200) > 0)
  {
      Console.WriteLine("異步線程完成數未大於0,主線程繼續甘其他事!");
  }
//WaitAll:
WaitHandle[] waitHandleList = new WaitHandle[] { result.AsyncWaitHandle };
  //是否全部異步線程完成
  while (!WaitHandle.WaitAll(waitHandleList, 200))
  {
      Console.WriteLine("異步線程未全部完成,主線程繼續幹其他事!");
  }
//IAsyncResult回調函數
//倒數第二個參數,委託中綁定了完成後的回調方法
IAsyncResult result1 = myDelegate.BeginInvoke("小明",23, new AsyncCallback(Completed), null);
//供異步線程完成回調的方法
        static void Completed(IAsyncResult result)
        {
            //獲取委託對象,調用EndInvoke方法獲取運行結果
            AsyncResult _result = (AsyncResult)result;
            MyDelegate myDelegaate = (MyDelegate)_result.AsyncDelegate;
            //獲得參數
            string data = myDelegaate.EndInvoke(_result);
            Console.WriteLine(data);
            //異步線程執行完畢
            Console.WriteLine("異步線程完成咯!");
            Console.WriteLine("回調函數也是由" + Thread.CurrentThread.Name + "調用的!");
        }
    }
//回調函數依然是在輔助線程中執行的,這樣就不會影響主線程的運行。
//線程池的線程默認是後台線程。但是如果主線程比輔助線程優先完成,那麼程序已經卸載,回調函數未必會執行。如果不希望丟失回調函數中的操作,要麼把異步線程設為前台線程,要麼確保主線程將比輔助線程遲完成。

//BeginInvoke("劉備",23, new AsyncCallback(Completed), null)最後一個參數用來傳參
Person p = new Person(2,"關羽");
IAsyncResult result1 = myDelegate.BeginInvoke("劉備", 23, new AsyncCallback(Completed), p);
//供異步線程完成回調的方法
        static void Completed(IAsyncResult result)
        {
            //獲取委託對象,調用EndInvoke方法獲取運行結果
            AsyncResult _result = (AsyncResult)result;
            MyDelegate myDelegaate = (MyDelegate)_result.AsyncDelegate;
            //獲得參數
            string data = myDelegaate.EndInvoke(_result);
            Console.WriteLine(data);

            Person p = result.AsyncState as Person;
            Console.WriteLine("傳過來的參數是:" + p.Name);
            //異步線程執行完畢
            Console.WriteLine("異步線程完成咯!");
            Console.WriteLine("回調函數也是由" + Thread.CurrentThread.Name + "調用的!");
        }