C# 的線程

來源:互聯網
上載者:User

標籤:機率   代碼   線程   問號   tgt   主線程   運行   上下文   支援   

第1部分:起步

介紹和概念

c#支援通過多線程並存執行代碼。線程是一個獨立的執行路徑,能夠與其他線程同時運行。

 

一個c#用戶端程式(控制台、WPF或Windows表單)從一個由CLR和作業系統(“主”線程)自動建立的線程開始,並且通過建立額外的線程來實現多線程。下面是一個簡單的樣本及其輸出:

 

所有的樣本都假設匯入了以下名稱空間:

 

使用系統;

使用System.Threading;

類ThreadTest

{

靜態void Main()

{

線程t = new Thread(WriteY);/ /啟動一個新線程

t.Start();/ /運行WriteY()

 

/ /同時,在主線程上做一些事情。

for(int i = 0;i < 1000;i + +)控制台。寫(“x”);

}

 

靜態孔隙WriteY()

{

for(int i = 0;i < 1000;i + +)控制台。寫(“y”);

}

}

xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyy

yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxx

xxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

yyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

……

主線程建立一個新的線程t,它運行一個重複列印字元“y”的方法。同時,主線程反覆列印字元“x”:

 

開始一個新的線程

一旦啟動,線程的IsAlive屬性將返回true,直到線程結束。當傳遞到線程的建構函式的委託完成執行時,線程結束。一旦結束,線程無法重新啟動。

 

CLR將每個線程分配其自己的記憶體堆棧,這樣本地變數就會保持分離。在下一個樣本中,我們定義了一個帶有局部變數的方法,然後在主線程和新建立的線程上同時調用方法:

 

靜態void Main()

{

新線程(Go). start();/ /調用Go()在新線程上

Go();/ / Call Go()在主線程上

}

 

靜態空去()

{

/ /聲明並使用局部變數—“迴圈”

for(int cycle = 0;迴圈< 5;迴圈+ +)控制台。寫(‘ ? ‘);

}

? ? ? ? ? ? ? ? ? ?

每個線程的記憶體堆棧上都建立了一個單獨的迴圈變數副本,因此可以預見,輸出是10個問號。

 

如果線程共用同一個對象執行個體的公用引用,則共用資料。例如:

 

類ThreadTest

{

bool完成;

 

靜態void Main()

{

ThreadTest tt = new ThreadTest();/ /建立一個通用執行個體

新線程(tt.Go).Start();

tt.Go();

}

 

/ /注意,Go現在是一個執行個體方法

空去()

{

如果(完成){ done = true;控制台。WriteLine(“完成”);}

}

}

因為兩個線程都在同一個ThreadTest執行個體上調用Go(),它們共用完成的欄位。這樣做的結果是“完成”,而不是兩次。

 

完成

靜態欄位提供了線上程之間共用資料的另一種方法。這裡有一個與靜態欄位相同的例子:

 

類ThreadTest

{

靜態bool完成;/ /靜態欄位在所有線程之間共用

 

靜態void Main()

{

新線程(去).Start();

();

}

 

靜態空去()

{

如果(完成){ done = true;控制台。WriteLine(“完成”);}

}

}

這兩個例子都說明了另一個關鍵概念:安全執行緒(或者更確切地說,是安全執行緒)。輸出實際上是不確定的:有可能(儘管不太可能)“完成”可以列印兩次。但是,如果我們在Go方法中交換語句的順序,“完成”的機率就會急劇增加:

 

靜態空去()

{

如果(!){控制台。WriteLine(“Done”);Done = true;

}

完成

完成(通常是!)

問題是,一個線程可以對if語句進行評估,而另一個線程正在執行WriteLine語句——在它有機會設定為true之前。

 

補救辦法是在閱讀和寫作時獲得一個獨佔鎖。c#為這個目的提供了鎖語句:

 

類為

{

靜態彎曲件;

靜態readonly對象locker = new object();

 

靜態void Main()

{

新線程(去).Start();

();

}

 

靜態空去()

{

鎖(鎖)

{

如果(!){控制台。WriteLine(“Done”);Done = true;

}

}

}

當兩個線程同時爭用一個鎖(在本例中是一個鎖),一個線程等待,或者阻塞,直到鎖可用。在這種情況下,它只確保一個線程可以一次輸入關鍵的程式碼片段,並且“完成”將只列印一次。以這種方式保護的代碼—從多線程上下文中的不確定性—稱為安全執行緒。

 

共用資料是多線程中複雜性和模糊錯誤的主要原因。雖然通常是必要的,但要儘可能的簡單。

 

線程雖然被阻塞,但不會消耗CPU資源。

 

加入和睡眠

您可以通過調用它的聯結方法等待另一個線程結束。例如:

 

靜態void Main()

{

線程t =新線程

C# 的線程

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.