線程被定義為程序的執(zhí)行路徑。 每個線程定義一個獨(dú)特的控制流程。 如果應(yīng)用程序涉及復(fù)雜和耗時的操作(如數(shù)據(jù)庫訪問或某些緊張的I/O操作),那么設(shè)置不同的執(zhí)行路徑或線程通常會很有幫助,每個線程都執(zhí)行特定的工作。
線程是輕量級的過程。 使用線程的一個常見例子是由現(xiàn)代操作系統(tǒng)實(shí)現(xiàn)并發(fā)編程。 線程的使用節(jié)省了CPU周期的浪費(fèi)并提高了應(yīng)用程序的效率。
到目前為止,我們編譯的程序中,是以單個線程作為應(yīng)用程序運(yùn)行的實(shí)例來運(yùn)行。 但是,這樣應(yīng)用程序一次可以只可執(zhí)行一項(xiàng)工作。 為了一次執(zhí)行多個任務(wù),可以將其分成更小的線程。
在.Net中,線程是通過System.Threading命名空間處理的。 創(chuàng)建System.Threading.Thread類型的變量允許您創(chuàng)建一個新的線程開始使用。它允許創(chuàng)建和訪問程序中的各個線程。
一個線程是通過創(chuàng)建一個Thread類的對象來創(chuàng)建的,給它的構(gòu)造器一個ThreadStart引用。
ThreadStart childthreat = new ThreadStart(childthreadcall);
線程的生命周期在System.Threading.Thread類的對象被創(chuàng)建時開始,并在線程被終止或完成執(zhí)行時結(jié)束。
以下是線程生命周期中的各種狀態(tài):
Start方法的情況。Sleep方法已被調(diào)用Wait方法已被調(diào)用Thread類的Priority屬性指定一個線程相對于其他線程的優(yōu)先級。 .Net運(yùn)行時選擇具有最高優(yōu)先級的就緒線程。
優(yōu)先級可以被分類為:
當(dāng)線程被創(chuàng)建,它的優(yōu)先級就使用線程類的Priority屬性來設(shè)置。
NewThread.Priority = ThreadPriority.Highest;
Thread類具有以下重要的屬性:
| 編號 | 屬性 | 描述 |
|---|---|---|
| 1 | CurrentContext |
獲取線程正在執(zhí)行的當(dāng)前上下文。 |
| 2 | CurrentCulture |
獲取或設(shè)置當(dāng)前線程的文化。 |
| 3 | CurrentPrinciple |
獲取或設(shè)置線程當(dāng)前的基于角色的安全性的主體。 |
| 4 | CurrentThread |
獲取當(dāng)前正在運(yùn)行的線程。 |
| 5 | CurrentUICulture |
獲取或設(shè)置資源管理器在運(yùn)行時查找文化特定資源的當(dāng)前文化。 |
| 6 | ExecutionContext |
獲取一個ExecutionContext對象,其中包含有關(guān)當(dāng)前線程的各種上下文的信息。 |
| 7 | IsAlive |
獲取一個指示當(dāng)前線程執(zhí)行狀態(tài)的值。 |
| 8 | IsBackground |
獲取或設(shè)置一個值,該值指示線程是否為后臺線程。 |
| 9 | IsThreadPoolThread |
獲取一個值,該值指示線程是否屬于托管線程池。 |
| 10 | ManagedThreadId |
獲取當(dāng)前托管線程的唯一標(biāo)識符。 |
| 11 | Name |
獲取或設(shè)置線程的名稱。 |
| 12 | Priority |
獲取或設(shè)置一個指示線程調(diào)度優(yōu)先級的值。 |
| 13 | ThreadState |
獲取包含當(dāng)前線程狀態(tài)的值。 |
Thread類具有以下重要的方法:
| 編號 | 方法 | 描述 |
|---|---|---|
| 1 | Abort |
在調(diào)用它的線程中引發(fā)ThreadAbortException異常,以開始終止線程的過程。 調(diào)用這個方法通常會終止線程。 |
| 2 | AllocateDataSlot |
在所有線程上分配一個未命名的數(shù)據(jù)插槽。為了獲得更好的性能,請使用ThreadStaticAttribute屬性標(biāo)記字段。 |
| 3 | AllocateNamedDataSlot |
在所有線程上分配一個指定的數(shù)據(jù)插槽。 為了獲得更好的性能,請使用ThreadStaticAttribute屬性標(biāo)記字段。 |
| 4 | BeginCriticalRegion |
通知主機(jī)執(zhí)行即將進(jìn)入一個線程中止或未處理異常的影響可能危及應(yīng)用程序域中的其他任務(wù)的代碼區(qū)域。 |
| 5 | BeginThreadAffinity |
通知主機(jī)托管代碼即將執(zhí)行取決于當(dāng)前物理操作系統(tǒng)線程標(biāo)識的指令。 |
| 6 | EndCriticalRegion |
通知主機(jī)執(zhí)行即將進(jìn)入一個線程中止或未處理異常的影響被限制在當(dāng)前任務(wù)的代碼區(qū)域。 |
| 7 | EndThreadAffinity |
通知主機(jī),托管代碼已經(jīng)完成執(zhí)行取決于當(dāng)前物理操作系統(tǒng)線程的標(biāo)識的指令。 |
| 8 | FreeNamedDataSlot |
消除進(jìn)程中所有線程的名稱和插槽之間的關(guān)聯(lián)。 為了獲得更好的性能,請使用標(biāo)記為ThreadStaticAttribute屬性字段。 |
| 9 | GetData |
從當(dāng)前線程的當(dāng)前域內(nèi)的當(dāng)前線程的指定插槽中檢索值。 為了獲得更好的性能,請使用標(biāo)記為ThreadStaticAttribute屬性字段。 |
| 10 | GetDomain |
返回當(dāng)前線程正在運(yùn)行的當(dāng)前域。 |
| 11 | GetDomainID |
返回唯一的應(yīng)用程序域標(biāo)識符。 |
| 12 | GetNamedDataSlot |
查找一個命名的數(shù)據(jù)插槽。 為了獲得更好的性能,請使用ThreadStaticAttribute屬性標(biāo)記字段。 |
| 13 | Interrupt |
中斷處于WaitSleepJoin線程狀態(tài)的線程。 |
| 14 | Join |
阻塞調(diào)用線程,直到線程終止,同時繼續(xù)執(zhí)行標(biāo)準(zhǔn)COM和SendMessage抽取。這種方法有不同的重載形式。 |
| 15 | MemoryBarrier |
同步內(nèi)存訪問,如下所示:執(zhí)行當(dāng)前線程的處理器不能重新排序指令,以便在調(diào)用MemoryBarrier之前執(zhí)行內(nèi)存訪問之后,訪問MemoryBarrier調(diào)用之后的內(nèi)存訪問。 |
| 16 | ResetAbort |
取消當(dāng)前線程所請求的中止。 |
| 17 | SetData |
在當(dāng)前正在運(yùn)行的線程的指定槽中設(shè)置該線程當(dāng)前域的數(shù)據(jù)。為了獲得更好的性能,請使用標(biāo)記為ThreadStaticAttribute屬性的字段。 |
| 18 | Start |
開始一個線程。 |
| 19 | Sleep |
使線程暫停一段時間。 |
| 20 | SpinWait |
使線程等待迭代參數(shù)定義的次數(shù)。 |
| 21 | VolatileRead() |
讀取一個字段的值。該值是計(jì)算機(jī)中任何處理器寫入的最新值,無論處理器的數(shù)量或處理器高速緩存的狀態(tài)如何。這種方法有不同的重載形式。 |
| 22 | VolatileWrite() |
立即將值寫入字段,以便計(jì)算機(jī)中的所有處理器都可以看到該值。 這種方法有不同的重載形式。 |
| 23 | Yield |
使調(diào)用線程產(chǎn)生執(zhí)行到另一個準(zhǔn)備在當(dāng)前處理器上運(yùn)行的線程。 操作系統(tǒng)選擇要產(chǎn)生的線程。 |
以下示例說明了Thread類的用法。該頁面具有用于顯示來自子線程的消息的標(biāo)簽控件。 來自主程序的消息直接使用Response.Write()方法顯示。 因此,它們出現(xiàn)在頁面的頂部。
首先打開Visual Studio,創(chuàng)建一個名稱為:MultiThreading 的ASP.Net空網(wǎng)站 項(xiàng)目。并添加一個Web窗體文件 - Default.aspx
源文件(Default.aspx)如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>ASP.Net多線程示例</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h3>ASP.Net多線程示例</h3>
</div>
<asp:Label ID="lblmessage" runat="server" Text="Label">
</asp:Label>
</form>
</body>
</html>
后端代碼文件(Default.aspx.cs)如下:
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Threading;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ThreadStart childthreat = new ThreadStart(childthreadcall);
Response.Write("Child Thread Started <br/>");
Thread child = new Thread(childthreat);
child.Start();
Response.Write("Main sleeping for 2 seconds.......<br/>");
Thread.Sleep(2000);
Response.Write("<br/>Main aborting child thread<br/>");
child.Abort();
}
public void childthreadcall()
{
try
{
lblmessage.Text = "<br />Child thread started <br/>";
lblmessage.Text += "Child Thread: Coiunting to 10";
for (int i = 0; i < 10; i++)
{
Thread.Sleep(500);
lblmessage.Text += "<br/> in Child thread </br>";
}
lblmessage.Text += "<br/> child thread finished";
}
catch (ThreadAbortException e)
{
lblmessage.Text += "<br /> child thread - exception";
}
finally
{
lblmessage.Text += "<br /> child thread - unable to catch the exception";
}
}
}
請注意以下幾點(diǎn)
childthreadcall()方法來啟動一個新線程。主線程活動直接顯示在網(wǎng)頁上。2000毫秒,在此期間子線程執(zhí)行。ThreadAbortException異常并終止。運(yùn)行項(xiàng)目程序后,得到以下結(jié)果 -
