[.NET] 關於.NET線程問題總結(一)

基礎篇:

 

怎樣創建一個線程

我只簡單列舉幾種常用的方法,詳細可參考.Net多線程總結(一)

一)使用Thread類

ThreadStart threadStart=new ThreadStart(Calculate);//通過ThreadStart委託告訴子線程講執行什麼方法,這裏執行一個計算圓周長的方法
Thread thread=new Thread(threadStart);
thread.Start(); //啓動新線程

public void Calculate(){
double Diameter=0.5;
Console.Write("The perimeter Of Circle with a Diameter of {0} is {1}"Diameter,Diameter*Math.PI);
}
二)使用Delegate.BeginInvoke

delegate double CalculateMethod(double Diameter); //申明一個委託,表明需要在子線程上執行的方法的函數簽名
static CalculateMethod calcMethod = new CalculateMethod(Calculate);//把委託和具體的方法關聯起來
static void Main(string[] args)
{
//此處開始異步執行,並且可以給出一個回調函數(如果不需要執行什麼後續操作也可以不使用回調)
calcMethod.BeginInvoke(5, new AsyncCallback(TaskFinished), null);
Console.ReadLine();
}

//線程調用的函數,給出直徑作爲參數,計算周長
public static double Calculate(double Diameter)
{
    return Diameter * Math.PI;
}

//線程完成之後回調的函數
public static void TaskFinished(IAsyncResult result)
{
    double re = 0;
    re = calcMethod.EndInvoke(result);
    Console.WriteLine(re);
}

三)使用ThreadPool.QueueworkItem

WaitCallback w = new WaitCallback(Calculate);
//下面啓動四個線程,計算四個直徑下的圓周長
ThreadPool.QueueUserWorkItem(w, 1.0);
ThreadPool.QueueUserWorkItem(w, 2.0);
ThreadPool.QueueUserWorkItem(w, 3.0);
ThreadPool.QueueUserWorkItem(w, 4.0);
public static void Calculate(double Diameter)
{
return Diameter * Math.PI;
}

 

 

線程相關解釋:

 

一)受託管的線程與 Windows線程
必須要了解,執行.NET應用的線程實際上仍然是Windows線程。但是,當某個線程被CLR所知時,我們將它稱爲受託管的線程。具體來說,由受託管的代碼創建出來的線程就是受託管的線程。如果一個線程由非託管的代碼所創建,那麼它就是非託管的線程。不過,一旦該線程執行了受託管的代碼它就變成了受託管的線程。

一個受託管的線程和非託管的線程的區別在於,CLR將創建一個System.Threading.Thread類的實例來代表並操作前者。在內部實現中,CLR將一個包含了所有受託管線程的列表保存在一個叫做ThreadStore地方。

CLR確保每一個受託管的線程在任意時刻都在一個AppDomain中執行,但是這並不代表一個線程將永遠處在一個AppDomain中,它可以隨着時間的推移轉到其他的AppDomain中。

從安全的角度來看,一個受託管的線程的主用戶與底層的非託管線程中的Windows主用戶是無關的。

二)前臺線程與後臺線程

啓動了多個線程的程序在關閉的時候卻出現了問題,如果程序退出的時候不關閉線程,那麼線程就會一直的存在,但是大多啓動的線程都是局部變量,不能一一的關閉,如果調用Thread.CurrentThread.Abort()方法關閉主線程的話,就會出現ThreadAbortException 異常,因此這樣不行。
後來找到了這個辦法: Thread.IsBackground 設置線程爲後臺線程。

msdn對前臺線程和後臺線程的解釋:託管線程或者是後臺線程,或者是前臺線程。後臺線程不會使託管執行環境處於活動狀態,除此之外,後臺線程與前臺線程是一樣的。一旦所有前臺線程在託管進程(其中 .exe 文件是託管程序集)中被停止,系統將停止所有後臺線程並關閉。通過設置 Thread.IsBackground 屬性,可以將一個線程指定爲後臺線程或前臺線程。例如,通過將 Thread.IsBackground 設置爲 true,就可以將線程指定爲後臺線程。同樣,通過將 IsBackground 設置爲 false,就可以將線程指定爲前臺線程。從非託管代碼進入托管執行環境的所有線程都被標記爲後臺線程。通過創建並啓動新的 Thread 對象而生成的所有線程都是前臺線程。如果要創建希望用來偵聽某些活動(如套接字連接)的前臺線程,則應將 Thread.IsBackground 設置爲 true,以便進程可以終止。
所以解決辦法就是在主線程初始化的時候,設置:Thread.CurrentThread.IsBackground = true;

這樣,主線程就是後臺線程,在關閉主程序的時候就會關閉主線程,從而關閉所有線程。但是這樣的話,就會強制關閉所有正在執行的線程,所以在關閉的時候要對線程工作的結果保存。

發佈了44 篇原創文章 · 獲贊 4 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章