不可不知的C#基礎(chǔ) 3. 線程淺析
線程可以使你的項(xiàng)目運(yùn)行得更加的流暢.
什么是線程呢?
線程(thread)是程序執(zhí)行流的最小單元, 是程序中一個(gè)單一的順序控制流程. 每個(gè)程序最少有一個(gè)線程, 那就是程序本身.
在C#中, 你可以使用 System.Threading 提供的類,接口和方法實(shí)現(xiàn)線程的所有操作.
單線程操作
想象著你走進(jìn)快餐店, 大叫一聲"來(lái)碗蘭州拉面", 然后就坐在飯桌上等. 當(dāng)廚師聽到你的要求時(shí),他就開始做蘭州拉面了. 理論上講, 當(dāng)你叫了以后, 廚師就已經(jīng)收到了命令.
用代碼可以這樣表達(dá):
static void Main(string[] args)
{
string name = "蘭州拉面";
Console.WriteLine("來(lái)碗" + name);
PlaceOrder(name);
Console.WriteLine("坐在飯桌上....");
Console.Read();
}
static void PlaceOrder(string name)
{
Console.WriteLine("開始制作" + name);
}
static void PlaceOrder(string name)
{
Thread thread1 = new Thread(new ThreadStart(Cooking));
thread1.Start();
}
static void Cooking()
{
Console.Write("開始制作");
}
運(yùn)行程序, 你會(huì)發(fā)現(xiàn)輸出結(jié)果是:
這是表示雖然廚師聽到你的聲音了,但是你坐在飯桌上的動(dòng)作是在他開始做拉面之前. -- 更加的合情合理, 是嗎?
我們還可以引入?yún)?shù):
static void PlaceOrder(string name)
{
Thread thread1 = new Thread(t => Cooking(name));
thread1.Start();
}
static void Cooking(string name)
{
Console.WriteLine("開始制作" + name);
}
注意上面的參數(shù)的傳遞方法只用于.net 3.5/4
多線程
如果一個(gè)飯店有多個(gè)廚師, 并且同時(shí)有多個(gè)人點(diǎn)餐, 我們可以像這樣模擬實(shí)現(xiàn):
static void Main(string[] args)
{
string name = "蘭州拉面";
int number = 5;
Console.WriteLine("來(lái)" + number + "碗" + name);
PlaceOrder(name, 5);
Console.WriteLine("坐在飯桌上....");
Console.Read();
}
static void PlaceOrder(string name, int number)
{
for (int i = 0; i < number; i++)
{
Thread thread1 = new Thread(t => Cooking(name));
thread1.Start();
}
}
static void Cooking(string name)
{
Console.WriteLine("開始制作" + name);
}
運(yùn)行后, 結(jié)果顯示:
嗯, 有些廚師動(dòng)作還是快得像機(jī)器人, 讓我們給他們一些休息的時(shí)間:
static void Cooking(string name)
{
Thread.Sleep(10);
Console.WriteLine("開始制作" + name);
}
再次運(yùn)行程序, 結(jié)果是:
線程的關(guān)聯(lián)性和獨(dú)立性
線程的運(yùn)作是相對(duì)獨(dú)立的, 完成不同的工作. 但是它們卻是共享進(jìn)程內(nèi)的資源.
做個(gè)實(shí)驗(yàn):
static void PlaceOrder(string name, int number)
{
int[] array = new int[] {1000,500,300,500,1};
for (int i = 0; i < number; i++)
{
int time = array[i];
Thread thread1 = new Thread(t => Cooking(name, i,time));
thread1.Start();
}
}
static void Cooking(string name, int id, int time)
{
Thread.Sleep(10);
Console.WriteLine(id + "號(hào)開始制作" + name);
}
這里我們想給每一個(gè)廚師一個(gè)編號(hào), 但是當(dāng)把i 當(dāng)中參數(shù)傳遞的時(shí)候, visual studio 會(huì)發(fā)出警告:
" Access To Modified Closure “.
這個(gè)是什么意思呢? 運(yùn)行一下程序, 輸出是:
發(fā)現(xiàn)在運(yùn)行程序的時(shí)候, 錯(cuò)誤的讀取了廚師的編號(hào), 這就是那個(gè)警告發(fā)出的原因: 因?yàn)榫€程們共享的名字 i 在不停的變化中, 我們沒有辦法控制一個(gè)特定線程運(yùn)行時(shí)i 的值, -- 它們是相對(duì)獨(dú)立的.
解決方案就是增加一個(gè)變量名存放值作為傳遞:
static void PlaceOrder(string name, int number)
{
int[] array = new int[] {1000,500,300,500,1};
for (int i = 0; i < number; i++)
{
int j = i;
int time = array[i];
Thread thread1 = new Thread(t => Cooking(name, j,time));
thread1.Start();
}
}
static void PlaceOrder(string name, int number)
{
int[] array = new int[] {1000,500,300,500,1};
for (int i = 0; i < number; i++)
{
int j = i;
int time = array[i];
Thread thread1 = new Thread(t => Cooking(name, j,time));
thread1.Start();
}
}
static void Cooking(string name, int id, int time)
{
Thread.Sleep(10);
Console.WriteLine(id + "號(hào)開始制作" + name);
Thread.Sleep(time);
Console.WriteLine(id + "號(hào)準(zhǔn)備完畢,花費(fèi)時(shí)間:" + time);
}
請(qǐng)仔細(xì)讀讀上面的代碼和輸出的結(jié)果, 應(yīng)該大家都可以理解.
本文來(lái)自于喜樂的ASP.NET(Alex Song) 轉(zhuǎn)貼請(qǐng)注明出處







浙公網(wǎng)安備 33010602011771號(hào)