Asp.net 简明教程

ASP.NET - Multi Threading

线程定义为程序执行路径。每个线程定义一个独特的控制流程。如果您的应用程序包含复杂且耗时的操作,如数据库访问或一些密集 I/O 操作,那么通常通过每个线程执行特定任务来设置不同的执行路径或线程非常有用。

线程是轻量级进程。现代操作系统中实现并发编程的一个常见示例就是线程的使用。使用线程可以节省 CPU 周期并且提高应用程序的效率。

到目前为止,我们编译的程序是其中单个线程作为应用程序的运行实例运行单个进程。但是,通过该方式,应用程序可以一次执行一项任务。为了同时执行多个任务,它可以细分为更小的线程。

在 .Net 中,通过 'System.Threading' 命名空间处理线程。创建 System.Threading.Thread 类型的变量允许您创建一个新线程以开始使用。它允许您在程序中创建和访问各个线程。

Creating Thread

通过创建一个 Thread 对象,为其构造函数提供 ThreadStart 引用来创建线程。

ThreadStart childthreat = new ThreadStart(childthreadcall);

Thread Life Cycle

线程的生命周期从创建System.Threading.Thread类的对象时开始,并在线程终止或完成执行时结束。

以下是线程生命周期中的各个状态:

  1. The Unstarted State :这是创建线程实例的情况,但未调用 Start 方法。

  2. The Ready State :这是线程准备执行并等待 CPU 周期的状况。

  3. The Not Runnable State :当:调用了 Sleep 方法时调用了 Wait 方法时I/O 操作阻塞时线程不可运行

  4. The Dead State :这是线程完成执行或已中止的情况。

Thread Priority

Thread 类别的 Priority 属性指定一个线程相对于另一个线程的优先级。.Net 运行时选择具有最高优先级的就绪线程。

优先级可以分为:

  1. Above normal

  2. Below normal

  3. Highest

  4. Lowest

  5. Normal

一旦创建线程,其优先级使用线程类的 Priority 属性进行设置。

NewThread.Priority = ThreadPriority.Highest;

Thread Properties & Methods

Thread 类具有以下重要属性:

Property

Description

CurrentContext

获取线程正在执行的当前上下问。

CurrentCulture

获取或设置当前线程的语言环境。

CurrentPrinciple

获取或设置角色安全性的线程当前主体。

CurrentThread

获取当前运行的线程。

CurrentUICulture

获取或设置 Resource Manager 使用以在运行时查找特定于区域性的资源的当前区域性。

ExecutionContext

获取包含有关当前线程各种上下文的信息的 ExecutionContext 对象。

IsAlive

获取指示当前线程执行状态的值。

IsBackground

获取或设置指示线程是否是后台线程的值。

IsThreadPoolThread

获取指示线程是否属于托管线程池的值。

ManagedThreadId

获取指示当前托管的线程的唯一标识符。

Name

获取或设置线程的名称。

Priority

获取或设置指示线程调度优先级的值。

ThreadState

获取包含当前线程状态的值。

Thread 类有以下重要方法

Methods

Description

Abort

在调用该方法的线程中引发 ThreadAbortException,以开始终止线程的过程。调用此方法通常会终止该线程。

AllocateDataSlot

在所有线程上配置一个未命名的 data slot。为了提升性能,请使用标记了 ThreadStaticAttribute 特性的字段。

AllocateNamedDataSlot

在所有线程上配置一个命名的 data slot。为了提升性能,请使用标记了 ThreadStaticAttribute 特性的字段。

BeginCriticalRegion

通知主机,执行将进入该段代码区域,在这种代码区域中,线程中止或未处理的异常的影响可能危及应用程序域中的其他任务。

BeginThreadAffinity

通知主机,托管代码将执行依赖于当前物理操作系统线程标识的指令。

EndCriticalRegion

通知主机,执行将进入该段代码区域,在这种代码区域中,线程中止或未处理的异常的影响仅限于当前任务。

EndThreadAffinity

通知主机,托管代码已完成执行依赖于当前物理操作系统线程标识的指令。

FreeNamedDataSlot

消除进程中所有线程之间名称与 slot 之间的关联。为了提升性能,请使用标记了 ThreadStaticAttribute 特性的字段。

GetData

在当前线程的当前域中,从当前线程的指定 slot 中检索值。为了提升性能,请使用标记了 ThreadStaticAttribute 特性的字段。

GetDomain

返回当前线程正在运行的当前域。

GetDomainID

返回一个唯一的应用程序域标识符。

GetNamedDataSlot

查找已命名的 data 插槽。为了获得更好的性能,改为使用标记有 ThreadStaticAttribute 特性的字段。

Interrupt

中断处于 WaitSleepJoin 线程状态的线程。

Join

阻塞调用线程,直至一个线程终止,同时继续执行标准的 COM 和 SendMessage pump。此方法有不同的重载形式。

MemoryBarrier

按以下方式同步内存访问:执行当前线程的处理器不能重新排序指令,以便在调用 MemoryBarrier 之前的内存访问在调用 MemoryBarrier 之后的内存访问之后执行。

ResetAbort

取消对当前线程请求的已中止的请求。

SetData

为当前正在运行的线程的当前域设定当前线程指定插槽中的数据。为获得更好的性能,改为使用标记有 ThreadStaticAttribute 特性的字段。

Start

Starts a thread.

Sleep

使线程暂停一段 timespan。

SpinWait

使线程等待由 iterations 参数定义的次数。

VolatileRead()

读取字段的值。值是计算机中任何处理器最后写入的值,无论处理器数目或处理器缓存的状态如何。此方法有不同的重载形式。

VolatileWrite()

立即向字段写入一个值,以便计算机中的所有处理器都可见该值。此方法有不同的重载形式。

Yield

使调用线程向在当前处理器上准备好运行的另一个线程提交执行。操作系统选择要提交的线程。

Example

以下示例说明了 Thread 类的用途。页面有一个标签控件可用于显示来自子线程的消息。使用 Response.Write() 方法直接显示来自主程序的消息。因此,它们显示在页面的顶部。

源文件如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="threaddemo._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

   <head runat="server">
      <title>
         Untitled Page
      </title>
   </head>

   <body>
      <form id="form1" runat="server">
         <div>
            <h3>Thread Example</h3>
         </div>

         <asp:Label ID="lblmessage" runat="server" Text="Label">
         </asp:Label>
      </form>
   </body>

</html>

文件背后的代码如下:

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;

namespace threaddemo
{
   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";
         }
      }
   }
}

Observe the following

  1. 当加载该页面时,通过引用方法 childthreadcall() 启动了一个新线程。主线程活动直接显示在网页上。

  2. 第二个线程运行并向标签控件发送消息。

  3. 主线程休眠 2000 ms,在该期间内,子线程执行。

  4. 子线程运行,直至被主线程中止。它引发 ThreadAbortException 并终止。

  5. 控制权返回到主线程。

执行时,程序发送以下消息:

asp.net thread