博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET中的多线程整理
阅读量:5283 次
发布时间:2019-06-14

本文共 7822 字,大约阅读时间需要 26 分钟。

   线程,是操作系统中的术语,是操作系统进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以有很多线程,每条线程并行执行不同的任务。同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。我们把用来执行用户任务的线程称为工作线程。而线程池,是一种成熟的线程使用模式。

  为什么要创建线程池?

  线程池属于对象池.所有对象池都具有一个非常重要的共性,就是为了最大程度复用对象.那么,线程池的最重要的特征也就是最大程度利用线程。所以线程池的目的就是为了减少创建和切换线程的额外开销,利用已经的线程多次循环执行多个任务从而提高系统的处理能力.

  在ASP.NET工作进程中有两种线程池,Worker线程池处理所有传入的请求, I / O线程池处理的I / O(访问文件系统,Web服务和数据库等)。每个应用程序域都有其自己的线程池,可以排队到线程池的操作的数量只受可用内存的限制,然而,对线程池中的线程数的限制在这个过程中可以同时被激活。

  当我们发出一个(异步)页面请求。一个Worker线程就会被从Worker线程池中取出, 这个Worker线程会触发I/O操作。当I/O操作开始时,另一个线程将会被从I/O线程池中取出,在收到I/O线程的返回值之前,Worker线程会一直处于闲置状态。所以,如果你的页面加载事件触发了多个I/O操作,那么,Worker线程就很可能会被闲置很长时间。而线程池能够把正处于闲置状态的Worker线程回收,使他能够为其他的页面请求提供服务。从而,降低系统开销。

只要并发请求的数量不超过线程池的可用线程的数量,一切都很好。但是,当你正在构建企业级应用程序时,你的线程池中的线程的数量就会达到极限。当这种情况发生时,新的请求会进入请求队列。 而ASP.NET支持在它开始拒绝请求并返回错误503服务不可用之前的最大请求数量,但是,我还没搞清楚这个具体的数量值是多少。

以下为多线程示例:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Text;using System.Threading;using System.Data;using System.Data.SqlClient;using System.Configuration;namespace AsyncWeb{    public partial class ThreadAsync : System.Web.UI.Page    {        private string connect = ConfigurationManager.ConnectionStrings["ValvesTestConnectionString"].ConnectionString.ToString();        private DataTable threadOneResult;        private DataTable threadTwoResult;        private DataTable threadThreeResult;        protected void Page_Load(object sender, EventArgs e)        {            AsyncCallsWithThreadPool();        }        public void AsyncCallsWithThreadPool()        {            ThreadPool.QueueUserWorkItem(ThreadOne, 1000);            ThreadPool.QueueUserWorkItem(ThreadTwo, 5000);            ThreadPool.QueueUserWorkItem(ThreadThree, 10000);            while (threadOneResult == null ||                threadTwoResult == null ||                threadThreeResult == null)            {                Thread.Sleep(10000);            }            // continue            threadOneResult.Merge(threadTwoResult);            threadOneResult.Merge(threadThreeResult);            Output.DataSource = threadOneResult;            Output.DataBind();        }        private void ThreadOne(object state)        {            DataSet ds = new DataSet();            using (SqlConnection conn = new SqlConnection(connect))            {                SqlCommand cmd = new SqlCommand("SELECT top 10 header_id, line_id, ordered_item FROM oe_order_lines_all", conn);                SqlDataAdapter da = new SqlDataAdapter(cmd);                da.Fill(ds);            }            threadOneResult = ds.Tables[0];        }        private void ThreadTwo(object state)        {            DataSet ds = new DataSet();            using (SqlConnection conn = new SqlConnection(connect))            {                SqlCommand cmd = new SqlCommand("SELECT top 20 header_id, line_id, ordered_item FROM oe_order_lines_all", conn);                SqlDataAdapter da = new SqlDataAdapter(cmd);                da.Fill(ds);            }            threadTwoResult = ds.Tables[0];        }        private void ThreadThree(object state)        {            DataSet ds = new DataSet();            using (SqlConnection conn = new SqlConnection(connect))            {                SqlCommand cmd = new SqlCommand("SELECT top 30 header_id, line_id, ordered_item FROM oe_order_lines_all", conn);                SqlDataAdapter da = new SqlDataAdapter(cmd);                da.Fill(ds);            }            threadThreeResult = ds.Tables[0];        }    }}

在这个例子中,我在线程池中放了三个线程。当程序启动时,这三个线程就会被从线程池中取出,然后分别执行对应的操作,如从数据库中取数据。这三个线程在执行时,主线程会处于闲置状态,直到这三个线程完成主线程才会继续执行。我这里是使用While循环来实现的,其实还可以用其他方式实现。使用这种方式对线程的控制程度比较高,要特别小心的使用。ASP.NET也为开发人员提供了它自己的异步编程模型,一起来看看吧!

 

ASP.NET 中的异步编程模型

ASP.NET提供的异步编程模型包含:异步页(Asynchronous Page),Asynchronous Module 和 Asynchronous WebService。使用Asynchronous WebService实现异步的方式比较普遍,技术文档比较多。所以,本篇就不对Asynchronous WebService进行介绍。好了,开始吧!

异步页(Asynchronous Page)

  上图为普通页面和异步页面的生命周期事件。相对于普通的页面生存周期事件,异步页多了异步事件,上图绿色的部分就是异步事件在页面事件中的执行位置。我们可以很清楚的看到主线程被一分为二了,其实这里主线程还是在的,只不过被闲置了来等待异步线程的执行结束。开发人员可以通过在ASP.NET中注册(Begin,End)方法来实现异步操作。ASP.NET会调用Begin方法,在begin方法中去执行I/O操作,如执行数据库查询操作,ASP.NET将立即从Begin方法中返回而不会去等待返回值。ASP.NET只要检测到线程返回了,就会立即把这个线程放回到线程池中,然后,使用这个线程去处理其他的请求。

  从Begin方法中返回的是一个IAsyncResult 接口,正是通过这个接口ASP.NET才知道Begin方法什么时候结束。当Begin方法结束时,ASP.NET会到线程池中取出另一个线程去调用end方法。在end方法中,我们可以对返回值进行处理。

  从ASP.NET的角度看,这只是一个普通的请求,但是确由两个线程来执行。这会不会有什么问题呢?

  创建异步页的步骤很简单,首先在.aspx文件加入Async=”True”,目的就是程序在Runtime时告诉ASP.NET这是个异步页。如果是处理数据的异步请求,要在Connection String 中加“Asynchronous Processing=true;”。

如下示例:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Data;using System.Data.SqlClient;using System.Configuration;namespace AsyncWeb{    public partial class About : System.Web.UI.Page    {        private SqlConnection _connection;        private SqlCommand _command;        private SqlDataReader _reader;        protected void Page_Load(object sender, EventArgs e)        {            PageAsyncTask task = new PageAsyncTask(BeginAsyncOperation,            EndAsyncOperation,            TimeoutAsyncOperation,            null);            RegisterAsyncTask(task);         }        IAsyncResult BeginAsyncOperation(object sender, EventArgs e,        AsyncCallback cb, object state)        {            string connect = ConfigurationManager.ConnectionStrings["ValvesTestConnectionString"].ConnectionString.ToString();            _connection = new SqlConnection(connect);            _connection.Open();            _command = new SqlCommand(                "SELECT top 10 header_id, line_id, ordered_item FROM oe_order_lines_all", _connection);            return _command.BeginExecuteReader(cb, state);        }        void EndAsyncOperation(IAsyncResult ar)        {            _reader = _command.EndExecuteReader(ar);            DataTable dt = new DataTable();            dt.Load(_reader);            Output.DataSource = dt;            Output.DataBind();        }        void TimeoutAsyncOperation(IAsyncResult ar)        {            // Called if async operation times out (@ Page AsyncTimeout)            Label1.Text = "Data temporarily unavailable";        }        }    }

这是一个比较简单的例子。但是,ASP.NET实现异步页的步骤还是比较复杂的,至少比普通的页复杂很多。但是,从性能上考虑,新请求能够很快进入管道,并且不需要在应用程序请求队列中等待很长的时间,这样就使得整个应用程序的性能都得到了提高。

 

ASP.NET异步HttpHandlers

ASP.NET中第二种异步模式是使用HttpHandler, httphander通过文件的后缀名来确定请求类型然后再确定使用哪个处理方法。ASPX handler 用来处理来自.aspx页面的请求。, 简单的说,其实它就是一个实现了IHttpHandler接口的类,它包括IsReusable方法和ProcessRequest方法。ProcessRequest方法的主要工作就是处理HttpRequest并把它转化为HttpResponse, 再将HttpContext传到page中。

// Name this C# file HandlerTest.cs and compile it with the// command line: csc /t:library /r:System.Web.dll HandlerTest.cs.// Copy HandlerTest.dll to your \bin directory.using System.Web;namespace HandlerExample{   public class MyHttpHandler : IHttpHandler   {      // Override the ProcessRequest method.      public void ProcessRequest(HttpContext context)      {         context.Response.Write("

This is an HttpHandler Test.

"); context.Response.Write("

Your Browser:

"); context.Response.Write("Type: " + context.Request.Browser.Type + "
"); context.Response.Write("Version: " + context.Request.Browser.Version); } // Override the IsReusable property. public bool IsReusable { get { return true; } } }}/*______________________________________________________________To use this handler, include the following lines in a Web.config file.
*/

开发人员可以使用IHttpAsyncHandler来实现异步的HttpHandler。待续。。。。

转载于:https://www.cnblogs.com/Dannier/archive/2012/05/31/Thread.html

你可能感兴趣的文章
鸟哥私房菜基础篇:Linux 磁碟与档案系统管理习题
查看>>
垂直居中及水平垂直居中方案(共15种)
查看>>
JavaScript高级程序设计26.pdf
查看>>
jquery 对 table 的操作
查看>>
centos7 关闭防火墙
查看>>
Android 拍照图片选取与图片剪裁
查看>>
百度地图轨迹回放,自定义路书,边走边画线
查看>>
数字操作类
查看>>
NVME SSD vs SATA SSD(转)
查看>>
搜索实时个性化模型——基于FTRL和个性化推荐的搜索排序优化
查看>>
漫画解读“跨视图粒度计算”,了解有数分析利器
查看>>
【c++ primer读书笔记】【第3章】字符串、向量和数组
查看>>
ATL CAxWindow类创建问题一则
查看>>
【Android Developers Training】 31. 序言:共享简单数据
查看>>
【BZOJ】【2693】JZPTAB
查看>>
第八篇:ORM框架SQLAlchemy 了解知识
查看>>
JavaWeb学习笔记——过滤器
查看>>
Spring MVC学习笔记——完整的用户登录
查看>>
Spark学习笔记——安装和WordCount
查看>>
简单的弹出拖拽窗口(一)
查看>>