• ASP.NET服务器端多线程设计——异步IHttpHandler


    在.NET系统中,可以通过Thread直接创建线程。但为了避免使用过多的线程对系统性能做成影响,微软特别开发了一个ThreadPool(CLR线程池)对线程进行管理。

    ThreadPool.QueueUserWorkItem(new WaitCallback(method), objcet);//新建线程

    CLR线程池的线程却分成两种:工作者线程与IO线程
    ThreadPool.GetAvailableThreads(out int a1, out int a2);//a1为工作者线程,a2为IO线程

    一般ASP.NET的页面请求会在工作者线程中运行,但当使用硬盘文件读取,外部数据交换时就可以使用IO线程来降低工作者线程的压力。(注意:如果读取小型文件时异步使用IO线程,工作效率可能比单线程操作还要低,建议阁下参考Jeffrey Richter名著《CLR via C#》

    当客户端要获取网络文件时,一般会使用IHttpHandler方式,若是文件流量太大时,CLR线程池的工作者线程就被会长期占用并处于等待状态,当线程大于线程池的最大值 (IIS5.0默认值为25*CPU数,IIS 7.0默认值为250*CPU数)的时候,其他请求将处于等待状态,这样会对服务器造成压力。这时候可以通过异步的HttpHanlder利用IO线程对文件进行异步处理。其作用在于及时释放CLR线程池的工作者线程,将读取文件的工作交于异步IO线程。

    class File

    {

        FileStream fileStream;

        byte[] bytes;

    }

    public class Handler : IHttpAsyncHandler {     

          //异步HttpHandler继承于IHttpAsyncHandler,并包含BeginProcessRequest方法和EndProcessRequest方法
          public byte[] bytes;
          public HttpContext context1;

      

        public void ProcessRequest(HttpContext context)
         {
            throw new Exception();
          }
       
        public IAsyncResult BeginProcessRequest (HttpContext context,AsyncCallback callback,object o)

        {     
            context1 = context;

            //使用异步I/O线程时注意用下面方式建立FileStream对象,并把最后的参数userAsync设置为true
            //若文件大小小于缓冲值1024,那文件将一次性读取,回调时依然会使用CLR线程中池的工作者线程
            FileStream fileStream = new FileStream("E://My Webs/WebService1/TextFile.txt", 

                                                 FileMode.Open,FileAccess.Read,FileShare.Read, 1024, true );
            bytes = new byte[fileStream.Length];

            File file1=new File();

            file1.fileStream=fileStream;

            file1.bytes=bytes;
            return fileStream.BeginRead(file1.bytes, 0, (int)fileStream.Length, callback, file1);

            //此时,CLR线程池的工作者线程就会被及时释放,当完成读取时,再度调用IO线程完成操作。

        }

        public void EndProcessRequest(IAsyncResult result)
        {

            File file1 = (File)result.AsyncState;   
     
            file1.fileStream.EndRead(result);
            file1.fileStream.Close();    

            context1.Response.Write(System.Text.Encoding.UTF8.GetString(file1.bytes));        

             int n1,n2;

            ThreadPool.GetAvailableThreads(out n1, out n2);

            context1.Response.Write(String.Formate("WorkerThreads Count is {0}! ”+

                                           “ IOThreads Count is  {1} !",n1.ToString(),n2.ToString() ));

            //此时检测线程池,输出将会是WorkerThreads Count is 1000! IOThreads Count is 999!

            //说明异步方法使用的是IO线程 
        }

       

        public bool IsReusable {
            get {
                return false;
            }
        }

    }

    在使用WebService时,也可以使用异步调用的方式。

    http://www.pin5i.com/showtopic-10763.html

    同样对于SQL数据库,Socket,HttpWebRequest...也可使用异步进行访问。

    • DNS操作 BeginGetHostByName、BeginResolve。
    • Socket操作 BeginAccept、BeginConnect、BeginReceive等等。
    • WebRequest操作 BeginGetRequest、BeginGetResponse。
    • SqlCommand操作 BeginExecuteReader、 BeginExecuteNonQuery等等。这可能是开发一个Web应用时最常用的异步操作了。如果需要在执行数据库操作时得到IOCP支持,那么需 要在连接字符串中标记Asynchronous Processing为true(默认为false),否则在调用BeginXXX操作时就会抛出异常。

    但可惜此方式并不合适使用异步委托 ,当使用异步委托时(BeginInvoke,EndInvoke),系统所新增的线程同样来CLR线程池的工作者线程,如果麻木地使用异步方式,会适得其反,对系统的性能做成影响。

     

    ASP.NET服务器端多线程设计——异步Web服务

    ASP.NET服务器端多线程设计——异步IHttpHandler

    对 JAVA 开发有兴趣的朋友欢迎加入QQ群:174850571 共同探讨!
    对 .NET  开发有兴趣的朋友欢迎加入QQ群:162338858 共同探讨 !

  • 相关阅读:
    JVM 性能调优实战之:使用阿里开源工具 TProfiler 在海量业务代码中精确定位性能代码
    JVM 性能调优实战之:一次系统性能瓶颈的寻找过程
    MongoDB之一介绍(MongoDB与MySQL的区别、BSON与JSON的区别)
    spring之:XmlWebApplicationContext作为Spring Web应用的IoC容器,实例化和加载Bean的过程
    SpringBoot自动化配置之四:SpringBoot 之Starter(自动配置)、Command-line runners
    分析诊断工具之一:MYSQL性能查看(多指标)
    Condition-线程通信更高效的方式
    微服务监控之一:Metrics让微服务运行更透明
    游戏后台服务技术选型
    TCP之四:TCP 滑动窗口协议 详解
  • 原文地址:https://www.cnblogs.com/leslies2/p/1934161.html
Copyright © 2020-2023  润新知