前言
多線程編程是跨語言的,跨環境的,所以我們得學好它,對應用程序的性能提高是有幫助的。
閱讀目錄
一:System.Threading
二:Thread類
三:Thread說明
四:Thread的使用
五:運行機制
六:運行效果
一:System.Threading
提供一些使得可以進行多線程編程的類和接口,此命名空間包括管理線程組的ThreadPool類,可以在指定的時間后調用委托的Timer類,用於同步互斥線程的Mutex類。
二:Thread類
1. 啟動新的線程
Thread thread = new Thread(new ThreadStart(Count));Count是要被新的線程執行的函數,這個函數默認情況下是沒有參數的
2. 殺死線程
在殺死一個線程前,先判斷這個線程是否還活着(用IsAlive屬性),如果它已經死掉了,就不要在殺死它了,那就成鞭屍了沒有用的,如果它活着調用ABort方法來殺死此線程。
3. 暫停線程
讓一個運行的線程暫時停止運行即讓一個正常運行的線程休眠一段時間,如:thread.sheep(1000)即讓此線程休眠1秒鍾
4. 優先級
每個線程是不一樣的,它有優先級的,Thread 類中的ThreadPriority屬性用來設置優先級,但是不能保證操作系統會接受此優先級,一個線程的優先級分為五種,Normal(正常的),AboveNormal(超過正常的),BelowNormal(低於正常的),Highest(最高的),Lowest(最低的)。
5. 掛起線程
掛起線程是整個線程暫時停止了,掛起線程的整個暫停和暫停一個線程不一樣,暫停一個線程是讓一個正常運行的線程休眠一段時間,而掛起線程是把機子掛起來了,Thread類的Suspend方法用來掛起線程,直到調用Resume,此線程才能繼續執行,如果線程被掛起了,當然就不會起作用了。
舉個例子
比如你要抄臘肉,暫停線程相當於休息一會再炒臘肉,掛起線程就是把臘肉掛到牆上了,沒得抄了,恢復線程相當於把牆上的臘肉拿下來炒了。
6. 恢復線程
Resume用來恢復已經掛起的線程,讓它繼續執行,如果線程沒被掛起,當然也不會起作用了。
舉個例子
比如我控制5個機器人去探索月球,每個機器人相當於一個線程,每個機器人頭上有4個按鈕(啟動新的線程,暫停線程,掛起線程,恢復線程),我按一下啟動新的線程按鈕,這個機器人就開始工作了,我按一下暫停線程,機器人就停止工作了,這5個機器人相當於5個線程,同時並發執行探索月球的,你可以通過每個機器人頭上的按鈕,同時控制這5個機器人也相當於同時控制5個線程了。
三:Thread說明
1. 一個線程的方法是不帶任何參數的,同時也不返回任何值的,它的命名規則和一般方法一樣,可以是靜態方法,也可以是非靜態的方法,當這個方法執行完畢后,相應的線程也就結束了,這個線程的IsAlive屬性也就被設置為flase了。
2. .NET的公共語言運行時(CLR)能區分兩種不同類型的線程:即前台線程和后台線程,兩者的區別是前台線程是應用程序必須運行完所有的前台線程才能退出,而對於后台線程而言,應用程序不考慮其是否已經運行完畢而直接退出,所有的后台線程在應用程序退出后,就都自動結束了。
默認情況下都是前台線程 IsBackground = false。
四:Thread的使用
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace _1_ThreadClassExample
{
class Program
{
public static void ThreadProcess()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("ThreadProcess: {0}", i);
//阻塞當前的線程thread1,執行別的進程也就是Main這個進程,線程被阻塞的毫秒數為0則表示應掛起此線程(也就是thread1這個線程)以便其他等待線程能夠執行(也就是Main這個進程)
Thread.Sleep(0);
}
}
static void Main(string[] args)
{
Console.WriteLine("在主進程Main中啟動一個線程");
//創建一個線程
Thread thread1 = new Thread(new ThreadStart(ThreadProcess));
//啟動此線程
thread1.Start();
//創建一個線程
Thread thread2 = new Thread(new ThreadStart(ThreadProcess));
//啟動此線程
thread2.Start();
//掛起此線程
thread2.Suspend();
for (int i = 0; i < 4; i++)
{
Console.WriteLine("主進程Main輸出.....");
//阻塞當前的主進程Main,執行別的進程也就是thread1這個線程,線程被阻塞的毫秒數為0則表示應掛起此線程(也就是Main這個進程)以便其他等待線程能夠執行(也就是thread1這個線程)
Thread.Sleep(0);
}
Console.WriteLine("主線程Main調用線程Join方法直到thread1線程結束");
//阻塞調用線程,直到某個線程終止時為止,也就是說阻塞主進程Main,直到thread1線程執行完畢
thread1.Join();
Console.WriteLine("thread1線程結束");
thread2.Resume();//恢復掛起的線程
//thread2.IsBackground = true;
}
}
}
五:運行機制
在最開始輸出了“主進程Main輸出......”,緊跟着輸出了“ThreadProcess:1” ,又接着輸出了“主進程Main輸出......”,然后緊跟着是“ThreadProcess:2””,又接着輸出了“主進程Main輸出......”,然后緊跟着是“ThreadProcess:3””,它們交替出現,這是因為在for (int i = 0; i < 4; i++)中有句Thread.Sleep(0);的緣故,它的意思阻塞當前的主進程也就是Main這個主線程,執行別的進程,這個別的進程指的是thread1這個線程也就是ThreadProcess()這個函數,在ThreadProcess()這個函數中也有句Thread.Sleep(0);它的意思同樣也是阻塞當前的進程也就是thread1這個線程,執行別的進程,這里別的線程指的是Main這個主線程,所以它倆會交替出現,因為thread2這個線程被掛起了,所以暫時是不會被執行的,因為這個線程(臘腸)被掛到牆上了,只有我們恢復這個線程(也就是從牆上取下這個臘腸才能炒它),這個線程才會執行的,thread1.Join();的意思是阻塞調用線程,直到某個線程終止時為止,什么意思呢就是阻塞當前的主進程就是Main這個主進程,直到調用的線程也就是thread1這個線程執行完畢,所以你會看到連着輸出了“ThreadProcess:4”,“ThreadProcess:5”,,“ThreadProcess:6”等等直到,“ThreadProcess:9”結束,緊接着我們寫句thread2.Resume();恢復掛起的thread2這個線程,因為thread2這個線程執行的也是ThreadProcess()這個函數,所以最后你會看到連着輸出了“ThreadProcess:1”,“ThreadProcess:2”,“ThreadProcess:3”等等直到,“ThreadProcess:9”,結束,因為默認thread2.IsBackground = false;,也就是說thread2是前台線程,前台線程的特點是主進程必須等到線程執行完畢后才能結束,所以輸出“ThreadProcess:1”,“ThreadProcess:2”,“ThreadProcess:3”等等直到9,我們在更改代碼為thread2.IsBackground = true;雖然我們恢復了thread2這個線程,但是因為thread2.IsBackground = true,也就是說thread2是后台線程,后台線程的特點是主進程不等線程執行完畢就結束了,所以沒有輸出“ThreadProcess:1”,“ThreadProcess:2”,“ThreadProcess:3”等等直到9,主進程就自己結束了
六:運行效果
thread2.IsBackground = true;
thread2.IsBackground = false;