ASP.NET多线程技术解析
创始人
2024-04-19 00:01:56
0

前几天遇到了一个问题,我在页面逻辑里需要调用一个webservice,处理一个比较耗时的操作,但是我不需要知道其返回值。于是我希望ASP.NET能像winform一样使用自动生成的webservice异步方法,通过ASP.NET多线程来解决这一问题。

你是不是想说:在页面调用webservice的时候,直接调用其异步实现不就完了吗?

这其实是行不通的,为了实现异步调用,我们需要对页面进行小小的改动,在Page元素里加上Async=true

我们很快就会发现这样做的问题:

让我们测试一下吧,现在我们在一个webservice的Helloworld方法中放入一个Thread。Sleep(10000),然后调用他的异步实现。通过调试,我们可以发现虽然程序运行至HelloworldAsync时,非常快速的返回并往下运行,但是当所有逻辑处理完成后,页面并不Response,而是硬生生等待我们的线程睡醒了才返回。

可是如果我希望真正做到调了不管怎么办呢?

asp.net

你可以使用ASP.NET多线程中的Thread,或者ThreadPool,自己来启动一个线程,我推荐使用ThreadPool,这样的话,这些线程都会被iis的线程池管理起来,不会造成崩溃

我们来分析一下ASP.NET多线程这两种模式的运用有什么特点

WebService自带的异步模式为下图的模式

asp.net

这种模式适合无返回的情况,这种情况下,对子线程的调用应该越晚越好,我们可以看到,主、子线程共存的时间越短,我们的稀缺资源线程就越安全,请注意的是,也许总的执行时间不会比同步的情况更少,但是我们很快就返回了用户界面,所以用户体验能够得到提高

使用web多线程的缺点 :

看了上面的叙述,你也许会说,那干脆把我所有的调用都改成异步调用吧,你尽管去做吧,绝对是一场灾难,因为在异步的同时,一定一会产生一个新的线程等待调用的返回,即使你调用函数的返回值为void,所以异步调用的负面效果将是会产生许多子线程,所以注意当你的调用非常耗时,这个子线程也将长期占用你的线程池,如果这样的调用大量出现,照样会消耗掉所有的可用线程

那么什么情况下适合在web上使用哪种ASP.NET多线程模式呢

我们来看看这段伪代码,他的用途是提交一个报告,方法传入一个报告,并从一个WebService中获得一些报告的内容,接着插入数据库,然后在文件服务器上生成一个报告文件,最后发出一个通知,让我们逐条命令的过一下这个方法,看看什么地方适合改为异步调用?(记得我们的讨论都是基于web的,关于桌面运用的多线程请参考 多线程总结一)

  1. public void CreateReport(Report report){   
  2.    
  3. //从webservice上取得报告的一些信息,  
  4. 不取得这些信息报告,报告是不完整的,是不能提交的   
  5.    
  6. Report fullreport=CallWebService(report);   
  7.    
  8. //插入数据库,很重要的工作   
  9.    
  10. InsertIntoDataBase(fullreport)   
  11.    
  12. try{   
  13.    
  14. //生成报告文件,这里是一个耗时而且容易出错的操作   
  15.    
  16. WriteStaticFile(fullreport)   
  17.    
  18. }   
  19.    
  20. catch{//记录错误日志。。。。}   
  21.    
  22. //这个只是通知邮件   
  23.    
  24. CallMailService2(fullreport)   
  25.    
  26. }   

第一条语句CallWebService()从一个webservice里加载一些报告的内容,这个是业务逻辑相关的,因为如果不加载的话报告内容是不完整的,不能提交,显然不能改为异步调了不管的模式,在这里你可以尝试模式一,但是这个改动是没有作用的,因为其他所有的过程,包括插入数据库,生成报告都依赖于这个方法的返回,所以如果我们在这里使用异步的话,其他的所有操作都必须等待他的返回,所以采用异步除了多增加了线程以外,一点时间也不能节省

再来看插入数据库,和上面一样也没有必要使用异步调用

生成报告这里比较有趣,确实他是一个和逻辑息息相关的操作,但是通过分析代码,我们可以看出,虽然报告生成是一个重要业务步骤,但是并没有严格到说"如果不能生成报告,就必须回滚上面的操作",并且如果操作失败,在catch中也仅仅是记录了日志,并没有需要尝试重写的逻辑,(很有可能另外的某个程序或者某人,会定时查看日志,发现有错误就重新生成文件)也就是说,就这段代码而言,生成也可以算一个额外逻辑,那么自然也可以去异步操作.可是:千万注意!!

由于生成报告需要的时间较长,那么生成报告的子线程会长时间运行,长期无法返回线程池,如果请求量太大,频率太快,那就会耗尽线程资源了.

平心而论,这个问题其实不是异步造成的,即使时同步调用,执行此操作也需要化肥很长时间,调用量太大,频率太快,也会造成排队.而且由于返回时间太长,用户体验也不会好,所以我们的这个ASP.NET多线程的改造应该是有益的。

【编辑推荐】

  1. ASP.NET环境下的Shell函数
  2. 在ASP.NET中向数据库批量插入数据
  3. ASP.NET用Post方式向网页发送数据
  4. ASP.NET 2.0部署WEB应用程序浅析
  5. ASP.NET中的HttpWorkerRequest对像

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...