Thread類的基本用法1


一、             Thread類的基本用法

通過System.Threading.Thread類可以開始新的線程,並在線程堆棧中運行靜態或實例方法。可以通過Thread類的的構造方法傳遞一個無參數,並且不返回值(返回void)的委託(ThreadStart),這個委託的定義如下:

[ComVisibleAttribute(true)]

public delegate void ThreadStart()

我們可以通過如下的方法來建立並運行一個線程。

複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace MyThread
{
    
class Program
     {
        
public static void myStaticThreadMethod()
         {
             Console.WriteLine(
"myStaticThreadMethod");
         }
        
static void Main(string[] args)
         {
             Thread thread1 
= new Thread(myStaticThreadMethod);
             thread1.Start();  
// 只要使用Start方法,線程纔會運行
         }
     }
}
複製代碼

    除了運行靜態的方法,還可以在線程中運行實例方法,代碼如下:


複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace MyThread
{
    
class Program
     {
        
public void myThreadMethod()
         {
             Console.WriteLine(
"myThreadMethod");
         }
        
static void Main(string[] args)
         {
             Thread thread2 
= new Thread(new Program().myThreadMethod);
             thread2.Start();
         }
     }
}
複製代碼

    如果讀者的方法很簡單,或出去某種目的,也可以通過匿名委託或Lambda表達式來爲Thread的構造方法賦值,代碼如下:

Thread thread3 = new Thread(delegate() { Console.WriteLine("匿名委託"); });
thread3.Start();

Thread thread4 
= new Thread(( ) => { Console.WriteLine("Lambda表達式"); });
thread4.Start();

    其中Lambda表達式前面的( )表示沒有參數。

    爲了區分不同的線程,還可以爲Thread類的Name屬性賦值,代碼如下:


Thread thread5 = new Thread(() => { Console.WriteLine(Thread.CurrentThread.Name); });
thread5.Name 
= "我的Lamdba";
thread5.Start();

    如果將上面thread1至thread5放到一起執行,由於系統對線程的調度不同,輸出的結果是不定的,如圖1是一種可能的輸出結果。



                                                                 圖1

二、 定義一個線程類


    
我們可以將Thread類封裝在一個MyThread類中,以使任何從MyThread繼承的類都具有多線程能力。MyThread類的代碼如下:

複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace MyThread
{
   
abstract class MyThread
     {
        Thread thread 
= null;

       
abstract public void run();    

        
public void start()
         {
            
if (thread == null)
                 thread 
= new Thread(run);
             thread.Start();
         }
     }
}
複製代碼

    可以用下面的代碼來使用MyThread類。

複製代碼

class NewThread : MyThread
{
      
override public void run()
       {
           Console.WriteLine(
"使用MyThread建立並運行線程");
       }
   }

  
static void Main(string[] args)
   {

       NewThread nt 
= new NewThread();
       nt.start();
   }
複製代碼

 

     我們還可以利用MyThread來爲線程傳遞任意複雜的參數。詳細內容見下節。

三、     爲線程傳遞參數

Thread類有一個帶參數的委託類型的重載形式。這個委託的定義如下:

[ComVisibleAttribute(false)]

public delegate void ParameterizedThreadStart(Object obj)

這個Thread類的構造方法的定義如下:

 

public Thread(ParameterizedThreadStart start);

下面的代碼使用了這個帶參數的委託向線程傳遞一個字符串參數:

複製代碼
public static void myStaticParamThreadMethod(Object obj)
{
    Console.WriteLine(obj);
}

static void Main(string[] args)
{
      Thread thread 
= new Thread(myStaticParamThreadMethod);
      thread.Start(
"通過委託的參數傳值");
}
複製代碼

要注意的是,如果使用的是不帶參數的委託,不能使用帶參數的Start方法運行線程,否則系統會拋出異常。但使用帶參數的委託,可以使用thread.Start()來運行線程,這時所傳遞的參數值爲null。

    也可以定義一個類來傳遞參數值,如下面的代碼如下:

複製代碼
class MyData
{
    private String d1;
    private int d2;
    public MyData(String d1, int d2)
    {
    
this.d1 = d1;
    
this.d2 = d2;
    }
    public void threadMethod()
    {
        Console.WriteLine(d1);
      Console.WriteLine(d2);
    }
}

MyData myData 
= new MyData("abcd",1234);
Thread thread 
= new Thread(myData.threadMethod);
thread.Start();
複製代碼

    如果使用在第二節定義的MyThread類,傳遞參數會顯示更簡單,代碼如下:

複製代碼
class NewThread : MyThread
{
    
private String p1;
    
private int p2;
    
public NewThread(String p1, int p2)
     {
        
this.p1 = p1;
        
this.p2 = p2;
     }

    
override public void run()
     {
         Console.WriteLine(p1);
         Console.WriteLine(p2);
     }
}

NewThread newThread 
= new NewThread("hello world"4321);
newThread.start();
複製代碼

四、     前臺和後臺線程

    使用Thread建立的線程默認情況下是前臺線程,在進程中,只要有一個前臺線程未退出,進程就不會終止。主線程就是一個前臺線程。而後臺線程不管線程是否結束,只要所有的前臺線程都退出(包括正常退出和異常退出)後,進程就會自動終止。一般後臺線程用於處理時間較短的任務,如在一個Web服務器中可以利用後臺線程來處理客戶端發過來的請求信息。而前臺線程一般用於處理需要長時間等待的任務,如在Web服務器中的監聽客戶端請求的程序,或是定時對某些系統資源進行掃描的程序。下面的代碼演示了前臺和後臺線程的區別。

複製代碼
public static void myStaticThreadMethod()
{
    Thread.Sleep(
3000);
}

Thread thread 
= new Thread(myStaticThreadMethod);
// thread.IsBackground = true;
thread.Start();
複製代碼

    如果運行上面的代碼,程序會等待3秒後退出,如果將註釋去掉,將thread設成後臺線程,則程序會立即退出。

    要注意的是,必須在調用Start方法之前設置線程的類型,否則一但線程運行,將無法改變其類型。

    通過BeginXXX方法運行的線程都是後臺線程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章