ASP.NET - 多线程

线程被定义为程序的执行路径.每个线程都定义了一个独特的控制流.如果您的应用程序涉及复杂且耗时的操作(如数据库访问或一些强烈的I/O操作),则设置不同的执行路径或线程通常很有帮助,每个线程执行特定的工作.

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

到目前为止,我们编译的程序中单个线程作为单个进程运行,这是应用程序的运行实例.但是,这样应用程序可以一次执行一个作业.为了使它一次执行多个任务,它可以分成更小的线程.

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

创建线程

通过创建Thread对象创建线程,给出其构造函数一个ThreadStart引用.

ThreadStart childthreat = new ThreadStart(childthreadcall);

线程生命周期

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

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

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

  • 就绪状态:这是线程准备执行并等待CPU周期的情况.

  • 不可运行状态:线程无法运行,时间:

    • 睡眠方法被称为

    • 等待方法已被调用

    • 被I/O操作阻止

  • 死亡状态:线程已完成执行或已中止的情况.

线程优先级y

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

优先级可归类为:

  • 高于正常水平

  • 低于正常水平

  • 最高

  • 最低

  • 正常

创建线程后,使用线程类的Priority属性设置其优先级.

NewThread.Priority = ThreadPriority.Highest;

线程属性&方法

Thread类具有以下重要属性:

属性描述
CurrentContext获取线程执行的当前上下文.
CurrentCulture获取或设置当前线程的区域性.
CurrentPrinciple获取或设置线程的基于角色的安全性的当前主体.
CurrentThread获取当前正在运行的线程.
CurrentUICulture获取或设置资源管理器在运行时查找特定于文化的资源时使用的当前文化.
ExecutionContext获取一个ExecutionContext对象,其中包含有关各种上下文的信息.当前线程.
IsAlive获取一个指示执行状态的值当前线程.
IsBackground获取或设置一个值,指示是否或不是线程是后台线程.
IsThreadPoolThread获取一个值线程是否属于托管线程池.
ManagedThreadId获取当前托管线程的唯一标识符.
Name获取或设置线程的名称.
Priority获取或设置一个值指示线程的调度优先级.
ThreadState获取包含的值当前线程的状态.

Thread类具有以下重要方法:

Methods描述
Abort在调用它的线程中引发ThreadAbortException,以开始进程终止线程调用此方法通常会终止该线程.
AllocateDataSlot分配未命名的数据所有线程上的插槽.为了获得更好的性能,请使用标有ThreadStaticAttribute属性的字段.
AllocateNamedDataSlot在所有线程上分配命名数据槽.为了获得更好的性能,请使用标有ThreadStaticAttribute属性的字段.
BeginCriticalRegion通知主机执行即将进入代码区域,其中线程中止或未处理异常的影响可能会危及应用程序域中的其他任务.
BeginThreadAffinity通知主机托管代码即将执行依赖于当前物理操作系统线程标识的指令.
EndCriticalRegion通知主机执行即将进入代码区域其中线程中止或未处理异常的影响仅限于当前任务.
EndThreadAffinity通知主机托管代码已完成执行依赖于当前物理操作系统身份的指令t hread.
FreeNamedDataSlot消除名称和插槽之间的关联,对于流程中的所有线程.为了获得更好的性能,请使用标有ThreadStaticAttribute属性的字段.
GetData从当前线程的当前域中的当前线程的指定槽中检索值.为了获得更好的性能,请使用标有ThreadStaticAttribute属性的字段.
GetDomain返回当前线程正在运行的当前域.
GetDomainID返回唯一的应用程序域标识符.
GetNamedDataSlot查找命名数据槽.为了获得更好的性能,请使用标有ThreadStaticAttribute属性的字段.
Interrupt中断处于WaitSleepJoin线程状态的线程.
Join阻塞调用线程,直到线程终止,同时继续执行标准COM和SendMessage抽取.此方法具有不同的重载形式.
MemoryBarrier同步内存访问,如下所示:执行当前线程的处理器无法重新排序指令,使得在调用MemoryBarrier之前的内存访问在对MemoryBarrier的调用之后的内存访问之后执行.
ResetAbort取消当前线程请求的中止.
SetData为当前运行的线程设置该线程当前域的指定槽中的数据.为了获得更好的性能,请使用标记为ThreadStaticAttribute属性的字段.
Start开始一个帖子.
Sleep让线程暂停一段时间时间.
SpinWait导致线程等待次数由iterations参数定义.
VolatileRead()读取值一个领域.该值是计算机中任何处理器写入的最新值,无论处理器数量或处理器缓存状态如何.此方法具有不同的重载形式.
VolatileWrite()写入一个值立即到一个字段,以便该值对计算机中的所有处理器可见.此方法具有不同的重载形式.
Yield使调用线程成为将执行生成到另一个准备在当前处理器上运行的线程.操作系统选择要收益的线程.

示例

以下示例说明了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";
         }
      }
   }
}

观察以下

  • 加载页面时,将使用方法childthreadcall()的引用启动新线程.主要线程活动直接显示在网页上.

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

  • 主线程休眠2000毫秒,在此期间子线程执行.

  • 子线程运行直到它由主线程中止.它引发ThreadAbortException并终止.

  • 控制返回主线程.

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

ASP.NET线程