ASP.NET的后台Long-Running任务

简介:

首先,不推荐在ASP.NET后台中,启动Long-Running的任务。因为无论是用的Task还是ThreadPool.QueueUserWorkItem,ASP.NET不会知道它们在后台运行,这会产生一些问题,比如:

当修改web.config的时候,会触发Appdomain被回收(尽管此时IIS web服务器进程w3wp.exe仍然活着),IIS本身也会每29小时回收应用程序池,这都会导致后台线程被终止,从而引发异常。

当ASP.NET要回收AppDomain,它会让已经存在的请求处理完再回收,ASP.NET和IIS服务器也知道这些请求正在运行,所以等它们完成。问题是ASP.NET不知道任何后台线程比如一个计时器或者其他,它只知道和request相关的操作。

事实上,在后台长时间的运行某些任务实在不是web server该做的事情,通常都可以用其他的方式来避免这样做,比如:

用console application和windows任务管理器,或者使用Windows服务等。

但是,如果确定要这样做,那么在ASP.NET中也有些办法保证后台任务能够安全的退出。

方法一,使用IRegisteredObject接口。

通过IRegisteredObject接口,并且调用HostingEnvironment.RegisterObject方法在ASP.NET中注册它。

当Appdomain要被回收的时候,会调用已注册对象中的IRegisteredObject中的Stop方法。

1
public  interface  IRegisteredObject {  void  Stop( bool  immediate); }

已注册对象没有被取消注册(即没有调用HostingEnvironment.UnregisterObject方法来取消注册),那么Stop方法会被调用两次,第一次调用的时候,immediate参数为false,此时如果已注册对象已经停止了,那么应该调用 HostingEnvironment.UnregisterObject方法来取消注册。如果还不取消注册,那么30秒后,该方法会被再次执行(这是最后的机会),不同的是此时传入的immediate参数为true,此时注册对象必须先调用 UnregisterObject 方法然后返回;否则应用程序管理器将移除该对象的注册。

使用IRegisteredObject接口并不是用来处理后台Long-Running任务的,但是这个功能可以让你安全的退出后台任务。

举个例子,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public  class  JobHost : IRegisteredObject
{
     private  readonly  object  _lock =  new  object ();
     private  bool  _shuttingDown;
     public  JobHost()
     {
         HostingEnvironment.RegisterObject( this );
     }
     public  void  Stop( bool  immediate)
     {
         lock  (_lock)
         {
             _shuttingDown =  true ;
         }
         HostingEnvironment.UnregisterObject( this );
     }
     public  void  DoWork(Action work)
     {
         lock  (_lock)
         {
             if  (_shuttingDown)
             {
                 return ;
             }
             work();
         }
     }
}

如上面的代码,ASP.NET要回收Appdomain时,Stop 方法会被调用,这个方法会获得一个锁,在DoWork方法也获得同样的所,这样的话,DoWork在运行的时候,Stop方法不得不等待。

方法二,使用HostingEnvironment.QueueBackgroundWorkItem

HostingEnvironment.QueueBackgroundWorkItem 方法在.NET4.5.2中引入,QueueBackgroundWorkItem (QBWI) 通过ASP.NET运行时,注册后台任务。这样的话,由于ASP.NET知道有后台任务,他就不会立即回收Appdomain,当然,这不意味着后台任务可以做任何事情。当ASP.NET需要做回收的时候,它可以通过一个CancellationToken通知后台任务,并且等待30s让工作完成。如果30秒内没问出,那么这个工作也会消失了。关于QueueBackgroundWorkItem的更多细节,可以通过

http://blogs.msdn.com/b/webdev/archive/2014/06/04/queuebackgroundworkitem-to-reliably-schedule-and-run-long-background-process-in-asp-net.aspx学习。

方法二,使用HangFire

HangFire是一个开源的类库,提供简单的方法在ASP.NET中执行后台Long-Running任务。这个类库需要一些额外的存储上的支持,SQLServer,Redis或者MSMQ。HangFire的资料在http://hangfire.io/

 

参考资料

http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/

http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html

http://blogs.msdn.com/b/tmarq/archive/2010/04/14/performing-asynchronous-work-or-tasks-in-asp-net-applications.aspx














本文转自cnn23711151CTO博客,原文链接:http://blog.51cto.com/cnn237111/1549947 ,如需转载请自行联系原作者







相关文章
|
4月前
|
存储 开发框架 .NET
Asp.Net第一章入门之后台处理程序
Asp.Net第一章入门之后台处理程序
30 0
|
5月前
|
缓存 开发框架 前端开发
基于.NET 7 + iView 的前后端分离的通用后台管理系统开源框架
基于.NET 7 + iView 的前后端分离的通用后台管理系统开源框架
44 0
|
9月前
|
存储 开发框架 .NET
WPF+ASP.NET SignalR实现后台通知
WPF+ASP.NET SignalR实现后台通知
81 0
|
9月前
|
前端开发
解决.NET Core Ajax请求后台传送参数过大请求失败问题
解决.NET Core Ajax请求后台传送参数过大请求失败问题
|
SQL 开发框架 前端开发
Asp.net core项目实战 新闻网站+后台 源码、设计原理、视频教程
Asp.net core项目实战 新闻网站+后台 源码、设计原理、视频教程
304 0
Asp.net core项目实战 新闻网站+后台 源码、设计原理、视频教程
|
开发框架 缓存 .NET
ASP.NET Core : 十一. 如何在后台运行一个任务
在大部分程序中一般都会需要用到后台任务, 比如定时更新缓存或更新某些状态。
180 0
|
存储 开发框架 缓存
ASP.NET Core : 十一. 如何在后台运行一个任务(上)
在大部分程序中一般都会需要用到后台任务, 比如定时更新缓存或更新某些状态。
158 0
|
开发框架 前端开发 .NET
|
开发框架 .NET 数据安全/隐私保护
基于ASP.Net Core开发的一套通用后台框架
基于ASP.Net Core开发的一套通用后台框架写在前面这是本人在学习的过程中搭建学习的框架,如果对你有所帮助那再好不过。如果您有发现错误,请告知我,我会第一时间修改。知其然,知其所以然,并非重复的造轮子。
18445 0
|
.NET 数据库 安全
ASP.NET | 从零到一实战分析对后台数据库增加数据、模糊查找、精确查找并展示
新建: 新建数据库mydb.mdf、添加表: 更新数据库; 右击数据库,选择属性,复制连接字符串;(这里之前做过了,就简单点过不做细节。
1303 0