轉載網址:http://www.knowsky.com/540518.html
.NET將關於多線程的功能定義在System.Threading名字空間中。因此,要使用多線程,必須先聲明引用此名字空間(using System.Threading;)。
a.啟動線程
顧名思義,“啟動線程”就是建立並啟動一個線程的意思,如下代碼可實現:
Thread thread1 = new Thread(new ThreadStart( Count));
其中的 Count 是將要被新線程執行的函數。
b.殺死線程
“殺死線程”就是將一線程斬草除根,為了不白費力氣,在殺死一個線程前最好先判斷它是否還活著(通過 IsAlive 屬性),然後就可以調用 Abort 方法來殺死此線程。
c.暫停線程
它的意思就是讓一個正在啟動並執行線程休眠一段時間。如 thread.Sleep(1000); 就是讓線程休眠1秒鐘。
d.優先順序
這個用不著解釋了。Thread類中hread PR iority屬性,它用來設定優先權,但不能保證 作業系統 會接受該優先順序。一個線程的優先順序可分為5種:Normal, AboveNormal, BelowNormal, Highest, Lowest。具體實現例子如下:
thread.Priority = ThreadPriority.Highest;
e.掛起線程
Thread類的Suspend方法用來掛起線程,直到調用Resume,此線程才可以繼續執行。如果線程已經掛起,那就不會起作用。
if (thread.ThreadState = ThreadState.Running)
{
thread.Suspend();
}
f.恢複線程
用來恢複已經掛起的線程,以讓它繼續執行,如果線程沒掛起,也不會起作用。
if (thread.ThreadState = ThreadState.Suspended)
{
thread.Resume();
}
下面將列出一個例子,以說明簡單的線程處理功能。此例子來自於協助文檔。
using System;
using System.Threading;
// Simple threading scenario: Start a static method running
// on a second thread.
public class ThreadExample {
// The ThreadProc method is called when the thread starts.
// It loops ten times, writing to the console and yielding
// the rest of its time slice each time, and then ends.
public static void ThreadProc() {
for (int i = 0; i < 10; i++) {
Console.WriteLine("ThreadProc: {0}", i);
// Yield the rest of the time slice.
Thread.Sleep(0);
}
}
public static void Main() {
Console.WriteLine("Main thread: Start a second thread.");
// The constructor for the Thread class requires a ThreadStart
// delegate that represents the method to be executed on the
// thread. C# simplifies the creation of this delegate.
Thread t = new Thread(new ThreadStart(ThreadProc));
// Start ThreadProc. On a un ip rocessor, the thread does not get
// any processor time until the main thread yields. Uncomment
// the Thread.Sleep that follows t.Start() to see the difference.
t.Start();
//Thread.Sleep(0);
for (int i = 0; i < 4; i++) {
Console.WriteLine("Main thread: Do some work.");
Thread.Sleep(0);
}
Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.");
t.Join();
Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program.");
Console.ReadLine();
}
}
此代碼產生的輸出類似如下內容:
Main thread: Start a second thread.
Main thread: Do some work.
ThreadProc: 0
Main thread: Do some work.
ThreadProc: 1
Main thread: Do some work.
ThreadProc: 2
Main thread: Do some work.
ThreadProc: 3
Main thread: Call Join(), to wait until ThreadProc ends.
ThreadProc: 4
ThreadProc: 5
ThreadProc: 6
ThreadProc: 7
ThreadProc: 8
ThreadProc: 9
Main thread: ThreadProc.Join has returned. Press Enter to end program.
在Visul C#中System.Threading 命名空間提供一些使得可以進行多線程編程的類和介面,其中線程的建立有以下三種方法:Thread、ThreadPool、Timer。下面就它們的使用方法逐個作一簡單介紹。
一、Thread
這也許是最複雜的方法,但它提供了對線程的各種靈活控制。首先你必須使用它的建構函式建立一個線程執行個體,它的參數比較簡單,只有一個ThreadStart 委託:public Thread(ThreadStart start);然後調用Start()啟動它,當然你可以利用它的Priority屬性來設定或獲得它的運行優先順序(enum ThreadPriority: Normal、 Lowest、 Highest、 BelowNormal、 AboveNormal)。
下例首先產生了兩個線程執行個體t1和t2,然後分別設定它們的優先順序,接著啟動兩線程(兩線程基本一樣,只不過它們輸出不一樣,t1為“1”,t2為“2”,根據它們各自輸出字元個數比可大致看出它們佔用CPU時間之比,這也反映出了它們各自的優先順序)。
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(Thread1));
Thread t2 = new Thread(new ThreadStart(Thread2));
t1.Priority = ThreadPriority.BelowNormal ;
t2.Priority = ThreadPriority.Lowest ;
t1.Start();
t2.Start();
}
public static void Thread1()
{
for (int i = 1; i < 1000; i++)
{//每運行一個迴圈就寫一個“1”
dosth();
Console.Write("1");
}
}
public static void Thread2()
{
for (int i = 0; i < 1000; i++)
{//每運行一個迴圈就寫一個“2”
dosth();
Console.Write("2");
}
}
public static void dosth()
{//用來類比複雜運算
for (int j = 0; j < 10000000; j++)
{
int a=15;
a = a*a*a*a;
}
}
以上程式運行結果為:
11111111111111111111111111111111111111111121111111111111111111111111111111111111111112
11111111111111111111111111111111111111111121111111111111111111111111111111111111111112
11111111111111111111111111111111111111111121111111111111111111111111111111111111111112
從以上結果我們可以看出,t1線程所佔用CPU的時間遠比t2的多,這是因為t1的優先順序比t2的高,若我們把t1和t2的優先順序都設為Normal,結果見下圖:
121211221212121212121212121212121212121212121212121212121212121212121
212121212121212121212121212121212121212121212121212121212121212121212
121212121212121212
從上例我們可看出,它的構造類似於win32的背景工作執行緒,但更加簡單,只需把線程要調用的函數作為委託,然後把委託作為參數構造線程執行個體即可。當調用Start()啟動後,便會調用相應的函數,從那函數第一行開始執行。
接下來我們結合線程的ThreadState屬性來瞭解線程的控制。ThreadState是一個枚舉類型,它反映的是線程所處的狀態。當一個Thread執行個體剛建立時,它的ThreadState是Unstarted;當此線程被調用Start()啟動之後,它的ThreadState是 Running; 在此線程啟動之後,如果想讓它暫停(阻塞),可以調用Thread.Sleep() 方法,它有兩個重載方法(Sleep(int )、Sleep(Timespan )),只不過是表示時間量的格式不同而已,當在某線程內調用此函數時,它表示此線程將阻塞一段時間(時間是由傳遞給 Sleep 的毫秒數或Timespan決定的,但若參數為0則表示掛起此線程以使其它線程能夠執行,指定 Infinite 以無限期阻塞線程),此時它的ThreadState將變為WaitSleepJoin,另外值得注意一點的是Sleep()函數被定義為了static。! 這也意味著它不能和某個線程執行個體結合起來用,也即不存在類似於t1.Sleep(10)的調用。正是如此,Sleep()函數只能由需“Sleep”的線程自己調用,不允許其它線程調用,正如when to Sleep是個人私事不能由它人決定。但是當某線程處於WaitSleepJoin狀態而又不得不喚醒它時,可使用Thread.Interrupt 方法 ,它將線上程上引發ThreadInterruptedException,下面我們先看一個例子(注意Sleep的調用方法):
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(Thread1));
t1.Start();
t1.Interrupt ();
E.WaitOne ();
t1.Interrupt ();
t1.Join();
Console.WriteLine(“t1 is end”);
}
static AutoResetEvent E = new AutoResetEvent(false);
public static void Thread1()
{
try
{//從參數可看出將導致休眠
Thread.Sleep(Timeout.Infinite);
}
catch(System.Threading.ThreadInterruptedException e)
{//中斷處理常式
Console.WriteLine (" 1st interrupt");
}
E.Set ();
try
{// 休眠
Thread.Sleep(Timeout.Infinite );
}
catch(System.Threading.ThreadInterruptedException e)
{
Console.WriteLine (" 2nd interrupt");
}//暫停10秒
Thread.Sleep (10000);
}
運行結果為:1st interrupt
2nd interrupt
(10s後)t1 is end
從上例我們可以看出Thread.Interrupt方法可以把程式從某個阻塞(WaitSleepJoin)狀態喚醒進入對應的中斷處理常式,然後繼續往下執行(它的ThreadState也變為Running),此函數的使用必須注意以下幾點:
1、此方法不僅可喚醒由Sleep導致的阻塞,而且對一切可導致線程進