Asp.Net的微信扎金花棋牌开发异步处理

2023-12-31 11:38

本文主要是介绍Asp.Net的微信扎金花棋牌开发异步处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Asp.Net的微信扎金花棋牌开发异步处理论坛:aqiulian.com,更多Asp.Net咨询Q:212303635.前几天看了两篇写的非常好的博文:详解.NET异步,详解 ASP.NET异步.在这两篇文章里,作者详细讲解了如何在.net中进行异步编程以及如何在asp.net中对请求进行异步处理.一开始看的时候有很多地方本人都看不懂,或者想不通.借着这股东风,我又重新把asp.net webForm模型复习了一遍,然后阅读了clr via c#,对.net异步处理进行了初步的研究.花了好几天功夫,终于大概能明白整个处理机制了.

      一.asp.net webForm 一般处理流程

      当IIS接收到客户端发来的请求后,如果发现这是请求一个asp.net资源,则通过调用HttpRuntime对像交由.net进行处理.HttpRuntime会创建一个HttpContext对象.这个上下文对象会伴随请求的整个生命周期.然后获取一个HttpApplication对象实例.请注意这里HttpContext对象是创建出来的,而HttpApplication是获取出来的.由于http请求是无状态的,所以在IIS看来,即使是相同的客户端,其每一次的请求也仍然是一次全新的请求.所以上下文对象每次是需要重新创建的.而HttpApplication对象则是处理请求的管道模型对象,只要服务器端的配置不发生变动,这个管道模型的各组件是不会发生变化的,所以不需要每一次都重新创建.为了实现高性能的对像复用.这里就有一个HttpApplication对象池.每当处理完请求后,HttpApplication对象就会重新回到池中以等待下一次被调用.

      上面说过,HttpApplication对象是管道模型对象,所以接下来就是各个HttpModule及真正处理请求的Ihttphandler对象,然后再次经过各个HttpModule对象回到HttpApplication对象,最后向客户端发出响应.

      二.闭包

      所谓闭包,就是使用的变量已经脱离其作用域,却由于和作用域存在上下文关系,从而可以在当前环境中继续使用其上文环境中所定义的一种函数对象.这个东东在动态语言里比较常见,比如JavaScript,如:

复制代码
function f1(){var n=999;return function(){return n;}
}
var a =f1();
alert(a());
复制代码

      这个局部变量n就是闭包.

      在.net中也有类似的东东.比如说匿名委托就是最常见的.那么在.net中是如何实现闭包语法的呢?这里就要用到反编译工具了.我用的是reflector.记得做一些设置:打开"View"菜单-->选择"Options",先去掉Show PDB symbols前的勾,然后把Optimization后的下拉框改为".Net 1.0"

      (一),不引用外部变量

复制代码
class Test
{public void GetData1(){Action action1 = new Action(() => Console.WriteLine("1"));}
}
复制代码

      经过反编译后的代码如下:

复制代码
[CompilerGenerated]
private static Action CS$<>9__CachedAnonymousMethodDelegate7;[CompilerGenerated]
private static void <GetData1>b__6()
{Console.WriteLine("1");
}public void GetData1()
{Action action = (CS$<>9__CachedAnonymousMethodDelegate7 != null) ? CS$<>9__CachedAnonymousMethodDelegate7 : (CS$<>9__CachedAnonymousMethodDelegate7 = new Action(Test.<GetData1>b__6));
}
复制代码

      可以看见这是最正常的处理,定义一个静态Action委托,一个静态方法,然后进行关联.

      (二).引用局部变量

复制代码
class Test
{public void GetData2(){int i = 10;int j = 20;Action action2 = new Action(() => Console.WriteLine(i + j));}
}
复制代码

      经过反编译后的代码如下:

复制代码
[CompilerGenerated]
private sealed class <>c__DisplayClass5
{// Fieldspublic int i;public int j;// Methodspublic void <GetData2>b__4(){Console.WriteLine((int) (this.i + this.j));}
}public void GetData2()
{<>c__DisplayClass5 class2 = new <>c__DisplayClass5();class2.i = 10;class2.j = 20;Action action = new Action(class2.<GetData2>b__4);
}
复制代码

      可以看见,当引用了局部变量后,Action委托里面的匿名方法就不再编译为所属类的一个静态方法,而是编译为一个内部类了,然后为这个内部类定义了两个公共字段i和j,分别对应引用的i与j,而Action真正包装的,是这个内部类的这个方法<GetData2>b__4.

      (三).引用所属类的属性

复制代码
class Test
{public int Number { get; set; }public void GetData3(){int i = 10;int j = 20;Data data = new Data() { Sum = 10 };Action action3 = new Action(() => Console.WriteLine(i + j + Number + data.Sum));}
}class Data
{public int Sum { get; set; }
}
复制代码

      经过反编译后的代码如下:

复制代码
[CompilerGenerated]
private sealed class <>c__DisplayClass2
{// Fieldspublic Test <>4__this;public Data data;public int i;public int j;// Methodspublic void <GetData3>b__1(){Console.WriteLine((int) (this.i + this.j + this.<>4__this.Number + this.data.Sum));}
}public void GetData3()
{<>c__DisplayClass2 class2 = new <>c__DisplayClass2();class2.<>4__this = this;class2.i = 10;class2.j = 20;Data data = new Data();data.Sum = 10;class2.data = data;Action action = new Action(class2.<GetData3>b__1);
}
复制代码

      可以看到,其处理方式基本与第二种情况一样,只不过在内部类里再加了一个所属类的公共字段.

      基本上到这里就清楚了,.net对闭包的实现,实际上是通过构造一个匿名类,把所有用到的资源引用到匿名类的同名共公字段上去来完成的.如上面例三,i,j,number,sum貌似是从Test类引用的,实际上是通用自己的匿名类引用的.这些对象生存周期也仍然没有违反.NET对象生命周期的规则.

      三.从同步到异步

      默认情况下,一个web服务器是可以同时对多个客户端请求进行响应的,显然,web服务器运行于多线程环境中.为了提高处理速度节约资源,他使用了.net的线程池.每当asp.net处理一个客户端请求的时候,其就从线程池里取出一个线程.当处理完成,相关信息返回给客户端的时候,此线程就返回池中以准备下一次的调用.

      如果客户端请求的数据非常复杂,需要经过长时候的计算,那么此线程就会被一直占用.这时如果服务器需要处理新的请求,就必需重新创建一个线程.被占用的线程越多,被占用的内存就越多,CPU上下文切换的次数也越多,性能也就越低下.

      另外还需要说明的是,线程是程序处理的基本单位,我们常说的栈,是在线程上的.程序里所有的资源都必需依附于某个线程.如下图所示:

      首先,线程池为处理asp.net请求调度了一个线程.这个线程处理asp.net生命周期里所涉及到的各个对象.当结果返回给客户端后重新回到线程池等待新的被调用.

      为了提高可能会长时间占用线程的请求的性能,.net提出了异步处理的概念.如下图所示:

      IhttpHandler对象是处理请求的核心对象.既然他处理的时间过长,那么就让他由原来的同步处理变成异步处理,同时把宝贵的线程资源归还给线程池.当异步处理完成后,再重新从线程池中获取一个新的线程完成以后的输出工作.

      四.异步的方式

      在.net中,异步的方式主要是两种:多线程与完成端口,或者跟据clr via C#的说法,叫计算限制与I/O限制.多线程,顾名思义就是利用多个线程并行执行任务,一般跟逻辑计算有关,主要消耗的资源是CPU与内存,所以又叫计算限制;而完成端口则是利用操作系统的特性,利用驱动程序来指导硬件来并行完成任务,比网络传输或文件读写,主要消耗硬件资源,所以又叫I/O限制.

      为了实现这两种异步,.net提供了多种异步编程模型:线程(池),基于线程池的Timer,Task,RegisterWaitForSingleObject,IAsyncResult APM, EAP(基于事件),AsyncEnumerator等等.其实主要就是两种:线程(池)与IAsyncResult APM.前者主要提供对多线程的支持,后者主要提供对完成端口的支持.当然,你在线程(池)里使用完成端口,在IAsyncResult APM里使用线程(池)也是可以的.

      五.asp.net异步

      asp.net异步的核心接口就是IHttpAsyncHandler.它使用的异步模型是IAsyncResult APM.这个接口有两个方法:IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)与void EndProcessRequest(IAsyncResult result),如下图所示:

      可以看到,HttpApplication对象调用了IHttpAsyncHandler对象的BeginProcessRequest方法使用的是一个线程.当BeginProcessRequest方法发起了一个异步调用后,这个线程就回归线程池了.异步调用完成后,重新从线程池里获取一个线程调用一个回调函数,接着调用了EndProcessRequest方法.下面有几小点值得注意.

      (一).对象生存周期.

      上面说过,在程序中所有的资源都需要附着在一个线程上.web线程调完IHttpAsyncHandler对象的BeginProcessRequest方法后就回归线程池了,那么HttpApplication对象是否也已回到了对象池,另一个线程调用HttpApplication对象回调方法,此对象与前一个对象是否是同一个对象呢?经过我的研究,结论是:他们是同一个对象.asp.net异步是通过回调方法来告知异步完成,那么必然就需要把HttpApplication对象回调方法的委托传入异步执行中.一方面,这个传入的过程其实也就是个闭包的过程:异步执行拥有HttpApplication对象的一个委托,HttpApplication对象不会随着web线程的回归而回归或消亡;另一方法,即使你不传入委托,不构成闭包,HttpApplication对象也不会随着web线程的回归而回归或消亡,不会消亡是因为还有HttpApplication对象池线程维持着对他的引用,不会回归则是因为你不回调委托,HttpApplication对象自己也不会智能的回到对象池.

      那么这就引出了另外一个问题:通过异步提高Web服务器的吞吐量的代价是什么.我认为的答案之一是内存占用量增大.原来是一个请求一个HttpApplication对象一个线程,请求:对象:线程=1:1:1,当线程足够大时,额外的请求请排队;现在是所有的请求都能进来,结果就是HttpApplication对象变多并等待处理,线程则处理应该处理的事情;是用HttpApplication对象池对象的增大来换取线程池线程的减少.其实我认为这是值得的,因为HttpApplication对象增多,只是占用了更多的内存,而线程池线程增多,则既占用了更多的内存又占用了更多的CPU.

      (二).asp.net的异步模型为什么是IAsyncResult APM.

      在.net中,一个CLR有且只能有一个线程池.那么意味着web线程就是从这唯一的线程池中来的,这也意味着其它线程池操作的线程来源与web线程的来源是一样的.asp.net异步的本意就是尽可能的释放线程,少占用线程,但是如果你的异步是用另一个线程池线程完成的,那么这和使用同一个线程,对线程池线程的占用量,有什么区别呢,仍然是一个请求占用一个线程,只不过是用两个线程组合起来而以.其性能理应比使用一个线程还要低,因为增加了CPU上下文切换.我想这也就是asp.net团队选取IAsyncResult APM异步模型的原因之一吧.

      当然,这不是否认不能用多线程来完成asp.net异步.在详解 ASP.NET异步这篇博文的留言中我看到了一个园友引用了老外的一些数据并自己总结了结论,我认为说的非常好.其实线程除了来自于线程池,也可以自己去构建,也可以把需要处理的逻辑发往其它机器去处理.只要你使用的线程不来自于线程池,就不会占用web线程或与其产生冲突.就能提高web服务器并发量.当然上面也说过,线程并非越多越好.线程的创建,销毁非常占用系统资源,也会增加CPU上下文切换率.web服务器的并发量并不是直线上升的,而是一个弧线,其增长率会越来越慢,到了一定程度甚至开始下降.在单服务器的情况下,并发量的增大是有限度的.真正想做到大并发量,还是像那么园友说的,使用单独的服务器吧.

      (三).两个线程

      当使用线程来实现异步时,最少会涉及两个线程.如上图所示,asp.net管道模型各对象的执行一直到IHttpAsyncHandler对象的BeginProcessRequest方法是一个线程,用蓝色表示;异步执行,HttpApplication对象的回调方法,IHttpAsyncHandler对象的EndProcessRequest方法及之后的asp.net管道模型各对象的执行是另一个线程,用紫色表示.

      六.应用

      我现在看到的最多的应用就是长连接了.这个例子网上很多,详解 ASP.NET异步这篇博文也写了很多,写的也比较好,这里我就不多说了.

 

      以上就是我的研究心得了,我仔细研究了clr via c#这本书,也参考了很多园友的文章.里面的结论有些来自于参考处,有些则是自己YY的.各位看官还需睁大眼睛.如有说的不对的地方,还请留言告知,水平有限,请多指教!

这篇关于Asp.Net的微信扎金花棋牌开发异步处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/555915

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get