ASP.NET多執行緒


執行緒被定義為程式的執行路徑。 每個執行緒定義一個獨特的控制流程。 如果應用程式涉及複雜和耗時的操作(如資料庫存取或某些緊張的I/O操作),那麼設定不同的執行路徑或執行緒通常會很有幫助,每個執行緒都執行特定的工作。

執行緒是輕量級的過程。 使用執行緒的一個常見例子是由現代作業系統實現並行程式設計。 執行緒的使用節省了CPU週期的浪費並提高了應用程式的效率。

到目前為止,我們編譯的程式中,是以單個執行緒作為應用程式執行的範例來執行。 但是,這樣應用程式一次可以只可執行一項工作。 為了一次執行多個任務,可以將其分成更小的執行緒。

在.Net中,執行緒是通過System.Threading名稱空間處理的。 建立System.Threading.Thread型別的變數允許您建立一個新的執行緒開始使用。它允許建立和存取程式中的各個執行緒。

建立執行緒

一個執行緒是通過建立一個Thread類的物件來建立的,給它的構造器一個ThreadStart參照。

ThreadStart childthreat = new ThreadStart(childthreadcall);

執行緒生命週期

執行緒的生命週期在System.Threading.Thread類的物件被建立時開始,並線上程被終止或完成執行時結束。

以下是執行緒生命週期中的各種狀態:

  • 未開始狀態:建立執行緒範例但未啟動Start方法的情況。
  • 就緒狀態:執行緒準備執行並等待CPU週期的情況。
  • 不可執行狀態:一個執行緒不可執行,當:
    • Sleep方法已被呼叫
    • Wait方法已被呼叫
    • 被I/O操作阻止
  • 死亡狀態:執行緒完成執行或被中止的情況。

執行緒優先

Thread類的Priority屬性指定一個執行緒相對於其他執行緒的優先順序。 .Net執行時選擇具有最高優先順序的就緒執行緒。

優先順序可以被分類為:

  • 超出正常水平
  • 低於一般
  • 最高
  • 最低
  • 正常

當執行緒被建立,它的優先順序就使用執行緒類的Priority屬性來設定。

NewThread.Priority = ThreadPriority.Highest;

執行緒屬性和方法

Thread類具有以下重要的屬性:

編號 屬性 描述
1 CurrentContext 獲取執行緒正在執行的當前上下文。
2 CurrentCulture 獲取或設定當前執行緒的文化。
3 CurrentPrinciple 獲取或設定執行緒當前的基於角色的安全性的主體。
4 CurrentThread 獲取當前正在執行的執行緒。
5 CurrentUICulture 獲取或設定資源管理器在執行時查詢文化特定資源的當前文化。
6 ExecutionContext 獲取一個ExecutionContext物件,其中包含有關當前執行緒的各種上下文的資訊。
7 IsAlive 獲取一個指示當前執行緒執行狀態的值。
8 IsBackground 獲取或設定一個值,該值指示執行緒是否為後台執行緒。
9 IsThreadPoolThread 獲取一個值,該值指示執行緒是否屬於託管執行緒池。
10 ManagedThreadId 獲取當前託管執行緒的唯一識別符號。
11 Name 獲取或設定執行緒的名稱。
12 Priority 獲取或設定一個指示執行緒排程優先順序的值。
13 ThreadState 獲取包含當前執行緒狀態的值。

Thread類具有以下重要的方法:

編號 方法 描述
1 Abort 在呼叫它的執行緒中引發ThreadAbortException異常,以開始終止執行緒的過程。 呼叫這個方法通常會終止執行緒。
2 AllocateDataSlot 在所有執行緒上分配一個未命名的資料插槽。為了獲得更好的效能,請使用ThreadStaticAttribute屬性標記欄位。
3 AllocateNamedDataSlot 在所有執行緒上分配一個指定的資料插槽。 為了獲得更好的效能,請使用ThreadStaticAttribute屬性標記欄位。
4 BeginCriticalRegion 通知主機執行即將進入一個執行緒中止或未處理異常的影響可能危及應用程式域中的其他任務的程式碼區域。
5 BeginThreadAffinity 通知主機受控代碼即將執行取決於當前物理作業系統執行緒標識的指令。
6 EndCriticalRegion 通知主機執行即將進入一個執行緒中止或未處理異常的影響被限制在當前任務的程式碼區域。
7 EndThreadAffinity 通知主機,受控代碼已經完成執行取決於當前物理作業系統執行緒的標識的指令。
8 FreeNamedDataSlot 消除進程中所有執行緒的名稱和插槽之間的關聯。 為了獲得更好的效能,請使用標記為ThreadStaticAttribute屬性欄位。
9 GetData 從當前執行緒的當前域內的當前執行緒的指定插槽中檢索值。 為了獲得更好的效能,請使用標記為ThreadStaticAttribute屬性欄位。
10 GetDomain 返回當前執行緒正在執行的當前域。
11 GetDomainID 返回唯一的應用程式域識別符號。
12 GetNamedDataSlot 查詢一個命名的資料插槽。 為了獲得更好的效能,請使用ThreadStaticAttribute屬性標記欄位。
13 Interrupt 中斷處於WaitSleepJoin執行緒狀態的執行緒。
14 Join 阻塞呼叫執行緒,直到執行緒終止,同時繼續執行標準COM和SendMessage抽取。這種方法有不同的過載形式。
15 MemoryBarrier 同步記憶體存取,如下所示:執行當前執行緒的處理器不能重新排序指令,以便在呼叫MemoryBarrier之前執行記憶體存取之後,存取MemoryBarrier呼叫之後的記憶體存取。
16 ResetAbort 取消當前執行緒所請求的中止。
17 SetData 在當前正在執行的執行緒的指定槽中設定該執行緒當前域的資料。為了獲得更好的效能,請使用標記為ThreadStaticAttribute屬性的欄位。
18 Start 開始一個執行緒。
19 Sleep 使執行緒暫停一段時間。
20 SpinWait 使執行緒等待疊代引數定義的次數。
21 VolatileRead() 讀取一個欄位的值。該值是計算機中任何處理器寫入的最新值,無論處理器的數量或處理器快取記憶體的狀態如何。這種方法有不同的過載形式。
22 VolatileWrite() 立即將值寫入欄位,以便計算機中的所有處理器都可以看到該值。 這種方法有不同的過載形式。
23 Yield 使呼叫執行緒產生執行到另一個準備在當前處理器上執行的執行緒。 作業系統選擇要產生的執行緒。

範例

以下範例說明了Thread類的用法。該頁面具有用於顯示來自子執行緒的訊息的標籤控制元件。 來自主程式的訊息直接使用Response.Write()方法顯示。 因此,它們出現在頁面的頂部。

首先開啟Visual Studio,建立一個名稱為:MultiThreadingASP.Net空網站 專案。並新增一個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";
        }
    }
}

請注意以下幾點

  • 載入頁面時,將使用childthreadcall()方法來啟動一個新執行緒。主執行緒活動直接顯示在網頁上。
  • 第二個執行緒執行並將訊息傳送到標籤控制元件。
  • 主執行緒休眠2000毫秒,在此期間子執行緒執行。
  • 子執行緒一直執行到主執行緒中止。它引發ThreadAbortException異常並終止。
  • 控制權返回到主執行緒。

執行專案程式後,得到以下結果 -