程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 不可不知的C#基礎 3. 線程淺析

不可不知的C#基礎 3. 線程淺析

編輯:C#入門知識

線程可以使你的項目運行得更加的流暢.

什麼是線程呢?

線程(thread)是程序執行流的最小單元, 是程序中一個單一的順序控制流程. 每個程序最少有一個線程, 那就是程序本身.

在C#中, 你可以使用 System.Threading 提供的類,接口和方法實現線程的所有操作.

單線程操作

想象著你走進快餐店, 大叫一聲"來碗蘭州拉面", 然後就坐在飯桌上等. 當廚師聽到你的要求時,他就開始做蘭州拉面了. 理論上講, 當你叫了以後, 廚師就已經收到了命令.

用代碼可以這樣表達:

 
	static void Main(string[] args)
{
    string name = "蘭州拉面";
    Console.WriteLine("來碗" + name);
    PlaceOrder(name);
    Console.WriteLine("坐在飯桌上....");
    Console.Read();
}
static void PlaceOrder(string name)
{
    Console.WriteLine("開始制作" + name);
}
  運行程序, 你會發現輸出結果是:

ScreenShot056

從顯示的結果來看, 這個廚師的動作非常的快, 他一聽到命令, 馬上就開始了. 為了讓這個程序的模擬比較真實, 我們可以想象"我的動作"是一個線程, 而"廚師做拉面"是一個線程. 如果我們運用線程來實現就有點意思了:  
	static void PlaceOrder(string name)
  {
      Thread thread1 = new Thread(new ThreadStart(Cooking));
      thread1.Start();
  }
  static void Cooking()
  {
      Console.Write("開始制作");
  }

運行程序, 你會發現輸出結果是:

ScreenShot055

 

這是表示雖然廚師聽到你的聲音了,但是你坐在飯桌上的動作是在他開始做拉面之前. -- 更加的合情合理, 是嗎?

我們還可以引入參數:

	static void PlaceOrder(string name)
{
    Thread thread1 = new Thread(t => Cooking(name));
    thread1.Start();
}
static void Cooking(string name)
{
    Console.WriteLine("開始制作" + name);
}

 

注意上面的參數的傳遞方法只用於.net 3.5/4

 

多線程

如果一個飯店有多個廚師, 並且同時有多個人點餐, 我們可以像這樣模擬實現:

	static void Main(string[] args)
 {
     string name = "蘭州拉面";
     int number = 5;
     Console.WriteLine("來" + 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);
 }

 

運行後, 結果顯示:

ScreenShot057

 

嗯, 有些廚師動作還是快得像機器人, 讓我們給他們一些休息的

 

再次運行程序, 結果是:

ScreenShot058

 

線程的關聯性和獨立性

線程的運作是相對獨立的, 完成不同的工作. 但是它們卻是共享進程內的資源.

做個實驗:

		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 + "號開始制作" + name);
}

這裡我們想給每一個廚師一個編號, 但是當把i 當中參數傳遞的時候, visual studio 會發出警告:

" Access To Modified Closure “.

這個是什麼意思呢? 運行一下程序, 輸出是:

 

ScreenShot059

 

發現在運行程序的時候, 錯誤的讀取了廚師的編號, 這就是那個警告發出的原因: 因為線程們共享的名字 i 在不停的變化中, 我們沒有辦法控制一個特定線程運行時i 的值, -- 它們是相對獨立的.

解決方案就是增加一個變量名存放值作為傳遞:

	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 + "號開始制作" + name);
    Thread.Sleep(time);
    Console.WriteLine(id + "號准備完畢,花費

	每個廚師的速度是不一樣的, 他們花費的時間不同, 所以先開始的不一定先完成, 上面的代碼運行的結果是:

	 

ScreenShot060

 

請仔細讀讀上面的代碼和輸出的結果, 應該大家都可以理解.

 

本文來自於喜樂的ASP.NET(Alex Song) 轉貼請注明出處

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved