C#線程開發之System.Thread類詳解

一、屬性

  • CurrentContext    獲取線程正在其中執行的當前上下文。
  • ExecutionContext    獲取 ExecutionContext 對象,該對象包含有關當前線程的各種上下文的信息。
  • CurrentCulture    獲取或設置當前線程的區域性。
  • CurrentUICulture    獲取或設置資源管理器使用的當前區域性以便在運行時查找區域性特定的資源。
  • CurrentThread    獲取當前正在運行的線程。
  • IsAlive    獲取指示當前線程的執行狀態的值。
  • IsBackground    獲取或設置一個值,該值指示某個線程是否為後臺線程。
  • IsThreadPoolThread    獲取指示線程是否屬於托管線程池的值。
  • ManagedThreadId    獲取當前托管線程的唯一標識符。
  • Name    獲取或設置線程的名稱。
  • Priority    獲取或設置指示線程的調度優先級的值。
  • ThreadState    獲取一個值,該值包含當前線程的狀態。

二、創建和控制線程

Thread 類的構造函數重載為接受ThreadStart和ParameterizedThreadStart類型的委托參數。
ThreadStart委托定義瞭一個返回類型為void的無參數方法。在創建瞭 Thread對象後,就可以用Start()方法啟動線程:

class Program
{
    static void Main()
    {
        var t1 = new Thread(ThreadMain);
        t1.Start();
        Console.WriteLine("This is the main thread.");
    }
    static void ThreadMain()
    {
        Console.WriteLine("Running in a thread.");
    }
}

Lambda表達式還可以與Thread類一起 使用,將線程方法的實現代碼傳送給Thread構造函數的實參:

static void Main()
{
    var t1 = new Thread(() => Console.WriteLine("running in a thread, id: {0}",Thread.CurrentThread.ManagedThreadId));
    t1.Start();
    Console.WriteLine("This is the main thread, id: {0}",
    Thread.CurrentThread.ManagedThreadId);
}

三、給線程傳遞參數

給線程傳遞一些數據可以采用兩種方式。

1、ParameterizedThreadStart委托參數

要給線程傳遞數據,需要某個存儲數據的類或結構。這裡定義瞭包含字符串的Data結構,但可以傳遞任意對象.

static void Main()
{
    var d = new Data { Message = "Info" };
    var t2 = new Thread(ThreadMainWithParameters);//ParameterizedThreadStart委托實例
    t2.Start(d);
}
static void ThreadMainWithParameters(object o)//如果使用瞭 ParameterizedThreadStart委托,線程的入口點必須有一個object類型的參數,且返回類型為void。
{
    Data d = (Data)o;
    Console.WriteLine("Running in a thread, received {0}", d.Message);
}
public struct Data
{
    public string Message;
}

2、創建一個自定義類,把線程的方法定義為實例方法

給新線程傳遞數據的另一種方式是定義一個類(參見MyThread類),在其中定義需要的字段,將線程的調用的方法定義為類的一個實例方法:

static void Main()
{
    var obj = new MyThread("info");
    var t3 = new Thread(obj.ThreadMain);//實例方法
    t3.Start();
}
//實例方法
public class MyThread
{
    private string data;
    public MyThread(string data)
    {
        this.data = data;
    }
    public void ThreadMain()
    {
        Console.WriteLine("Running in a thread, data: {0}", data);
    }
}

四、後臺線程

隻要有一個前臺線程在運行,應用程序的進程就在運行。
如果多個前臺線程在運行,而Main()方法結束瞭,應用程序的進程就仍然是激活的,直到所有前臺線程完成其任務為止。
在默認情況下,用Thread類創建的線程是前臺線程。線程池屮的線程總是後臺線程。
在用Thread類創建線程時,可以設置IsBackground屬性,以確定該線程是前臺線程還是後臺線程。

五、線程的優先級

在Thread類中,可以設置Priority屬性,以影響線程的基本優先級。Priority屬性需要ThreadPriority 枚舉定義的一個值。定義的級別有Highest、AboveNomal、BelowNormal和Lowest。

六、控制線程

  • 調用Thread對象的Start()方法,可以創建線程。但是,在調用Start()方法後,新線程仍不是處於Running狀態,而是處於Unstarted狀態。隻要操作系統的線程調度器選擇瞭要運行的線程,線程就會改為Running狀態。讀取Thread.ThreadState屬性,就可以獲得線程的當前狀態。
  • 使用ThreadSleep()方法,會使線程處於WaitSleepJoin狀態,在經歷Sleep()方法定義的時間段後,線程就會等待再次被喚醒。
  • 要停止另一個線程,可以調用Thread.Abort() 方法。調用這個方法時,會在接到終止命令的線程中拋出一個ThreadAbortExcepticm類型的異常。用一個處理程序捕獲這個異常,線程可以在結束前完成一些淸理工作。線程還可以在接收到調用Thread.ResetAbort()方法的結果ThreadAbortExcepdon 異常後繼續運行。如果線程沒有重置終止,接收到終止請求的線程的狀態就從AbortRequested改為 Aborted。
  • 如果需要等待線程的結束,就可以調用Thread.Join()方法。Thread.Join()方法會停止當前線程, 並把它設置為WaitSleepJoin狀態,直到加入的線程完成為止。
public class Worker
{
    // 此方法將在線程啟動時調用。
    public void DoWork()
    {
        while (!_shouldStop)
        {
            Console.WriteLine("工作線程: working...");
        }
        Console.WriteLine("工作線程:正常停止");
    }
    public void RequestStop()
    {
        _shouldStop = true;
    }
    // Volatile用於提示編譯器這個數據成員將被多個線程訪問。
    private volatile bool _shouldStop;
}

static void Main()
{
    // 創建thread對象,但這不會啟動線程。
    Worker workerObject = new Worker();
    Thread workerThread = new Thread(workerObject.DoWork);

    // 啟動工作線程。
    workerThread.Start();
    Console.WriteLine("main thread: 啟動工作線程...");

    // 循環,直到工作線程激活。
    while (!workerThread.IsAlive) ;

    // 將主線程休眠1毫秒,讓工作線程做一些工作:
    Thread.Sleep(1);

    // 請求工作線程停止自身:
    workerObject.RequestStop();//workerObject.Abort()

    //使用Join方法阻塞當前線程,直到工作線程執行完畢才往下執行
    workerThread.Join();
    Console.WriteLine("main thread: 工作線程已經終止.");
}

七、使用線程實現回調

//定義一個委托實現回調函數 
public delegate void CallBackDelegate(string message);

void Main()
{
    //委托實現方法和定義線程
    CallBackDelegate cbd = CallBack;
    Thread thread = new Thread(initFtpParam);
    thread.Start(cbd);
}

/// <summary>
/// 線程方法
/// </summary>
/// <param name="obj"></param>
public void initFtpParam(object obj)
{
    CallBackDelegate callBackDelegate = obj as CallBackDelegate;
    callBackDelegate("aa");//執行委托
}

/// <summary>
/// 回調方法
/// </summary>
/// <param name="message"></param>
private void CallBack(string message)
{
    Console.Write(message);
}

八、區域性和線程

  • CurrentUICulture屬性可返回當前用戶界面區域性。該屬性由 ResourceManager 類用於在運行時查找區域性特定資源。
    可以使用非特定區域性、特定區域性或 InvariantCulture 來設置 CurrentUICulture 屬性。
    默認值是操作系統用戶界面語言。
  • CurrentCulture屬性用來決定諸如貨幣、數字和日期如何格式化。
    CurrentCulture 屬性不是一個語言設置。它僅包含與地理區域的標準設置相關的數據。因此,隻能將 CurrentCulture 屬性設置為特定區域性,比如"fr-FR"或 InvariantCulture。
    默認值是操作系統的User Locale,我們可以在控制面板裡設置。CultureInfo.UseUserOverride屬性指示是否使用用戶在控制面板自定義的 數字、符號、日期、貨幣等的格式。

1、.NET4.5之前,隻能用以下代碼隻能針對單個線程,如果每次執行線程 都要重新設置一下。。。
新開一個新線程,默認的CurrentCulture為系統的Culture,如果要改變當前線程的Culture,需要在線程中修改 Thread.CurrentCulture值來實現。

m.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");

2、如果使用的.net環境是4.5及以上版本,CultureInfo提供瞭兩個靜態屬性DefaultThreadCulture和DefaultThreadUICulture,一處修改即可實現所有的未顯式設置Thread.CurrentCulture的線程都使用這個Default值。

System.Globalization.CultureInfo.DefaultThreadCurrentCulture = new System.Globalization.CultureInfo("en-US");
System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = new System.Globalization.CultureInfo("en-US");

到此這篇關於C#線程開發之System.Thread類的文章就介紹到這瞭。希望對大傢的學習有所幫助,也希望大傢多多支持LevelAH。

推薦閱讀: