c# FluentScheduler定时任务

参考链接:https://blog.csdn.net/kungc1/article/details/106409619/

                  https://www.cnblogs.com/xiaomen/p/6639566.html

                  https://blog.csdn.net/qmdweb/article/details/80970435

直接停止再开始IIS,就可以直接跑定时程序,不用再等时间。在 .Net 下类似的有微软的 Timer 、 Quartz.NET 、 FluentScheduler 以及Windows服务等,关于 Quartz.NET 的使用几乎和 Java 下的 Quartz 没什么区别。

在.Net中做定时任务中,我用到一个简单的框架FluentScheduler框架。这个框架可以让我们做一些定时的任务,如在启动时检查未来多少天的任务等等。这个框架是开源的,下载地址:https://github.com/fluentscheduler/FluentScheduler

.net 框架:.net framework 4.5,在winform,wpf之类的项目中使用是完全没有问题的。

 

 

首先可以通过VS2015这个开发工具中的NuGet管理器来引用即可。在项目引用上,右键管理NuGet程序包,输入FluentScheduler搜索,点击下载即可。

先在项目的Global.asax页面里添加初始化定时任务的代码,要在项目一开时初始化才行,这样项目一加载就开始执行检查。 

 

 

接下来就创建一个类来存放定时任务的代码,然后再写定时的代码。FluentScheduler框架提供了多种定时任务的方法,我这里时通过每天的定时来检查任务的。先创建你要执行定时的任务方法,该方法要调用IJob,然后再调用定时的方法。启动时执行一次,然后每天再执行一次

 

 

 

Schedule<TaskUpdateTwentyDayRoomInfo>.ToRunNow().AndEvery(1).Days().At(0,0) 这代码中,ToRunNow()是每次启动都会执行,AndEvery(1).Days是每一天都会执行检查,At(时,分)这就是定期检查的代码,当然用法不止这一种的,还有上面的几种。执行成功后,会在输出页面上显示出结果

Schedule().ToRunEvery(1 ).Hours().At(10); 注:在一个指定时间执行计划任务 每个小时的第10分钟执行。

上面需要注意的是NonReentrant函数的使用,在某些特殊的业务里可能任务执行的时间比定时循环的间隔时间要长,这时候你就要考虑是否允许并行运行两个同样的任务,NonReentrant就是用来解决这个问题的

在Controller中写

public class TimedTask : IJob, IRegisteredObject
    {
        private readonly object _lock = new object();

        private bool _shuttingDown;
        public Registry Start()
        {
            HostingEnvironment.RegisterObject(this);
            Registry registry = new Registry();       //每天几点执行一次代码
            registry.Schedule(() => Execute()).ToRunEvery(1).Days().At(01,00);
            return registry;
        }

        public void Execute()
        {lock (_lock)
            {
                if (_shuttingDown)
                {
                    return;
                }
                else
                {
                    //这里写每天固定时间要运行的代码
                }
            }
        }

        public void Stop(bool immediate)
        {
            lock (_lock)
            {
                _shuttingDown = true;
            }
            HostingEnvironment.UnregisterObject(this);
        }
    }

 所有的业务逻辑都在Execute函数中执行,如果不在web项目中运行,则不需要实现IRegisteredObject接口以及stop函数,所有的业务代码均在Execute函数中执行

实际上在asp.net 中的定时任务和FluentScheduler框架并没有什么必然的联系,你也可以用timer或其他的任何方式来实现,但是所有的这些实现方式都避免不了面对一个问题:IIS的回收机制

因为有了回收机制的存在,所以在asp.net中做定时任务就会面临两个问题:

1.任务没有执行完成线程就被回收了

2.线程回收之后,只有在下一次访问网站的时候任务才会再次启动

首先我们来解决第一个问题:

对于iis的回收,我们需要做的其实并不是阻止它的回收,实际上我试过各种方式都无法完全阻挡iis的回收,不知道是否是方法没有用对。

但是我们可以保证当前的任务执行完毕再进行回收

方式就是实现IRegisteredObject接口,以上面的MyJob类为例,我们通过调用HostingEnvironment.RegisterObject方法在ASP.NET中注册它

通过调用HostingEnvironment.UnregisterObject方法释放服务

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

  1.  
    //
  2.  
    // 摘要:
  3.  
    // Requests a registered object to unregister.
  4.  
    //
  5.  
    // 参数:
  6.  
    // immediate:
  7.  
    // true to indicate the registered object www.feifanyule.cn/ should unregister from the hosting environment
  8.  
    // before returning; www.089188.cn otherwise, false.
  9.  
    void Stop(bool immediate);

在第一次调用stop方法时,参数为false,执行完毕后,如果没有调用HostingEnvironment.UnregisterObject函数,隔30秒stop方法会再次被调用,参数为true,如果仍然没有调用HostingEnvironment.UnregisterObject函数,该服务就会被移除

不过我们使用的过程中并不会考虑第二次的调用,因为在第一次stop函数被调用的时候我们就会lock住正在执行的任务,并且一直到任务执行完成再释放lock,最后调用HostingEnvironment.UnregisterObject保证任务正常退出

对于这个流程上面的Myjob就是FluentScheduler提供的一个示例

IIS预加载

应用程序池回收之后,如果没有人访问网站,w3wp是不会启动的,那也就代表着我们的定时任务就不会启动了,所以我们需要在程序池被回收之后模拟访问一下该网站,我们可以通过写一个定时的程序每隔一秒钟访问一遍该网站来解决这个问题,但是为了解决这个问题多写一个程序并没有必要,因为微软已经提供了一个网站预加载的功能,每当应用程序池被回收,系统就会启动一个进程模拟访问一遍网站。这个功能似乎是iis7之后就有了,我下面演示的iis10的界面,其他版本的界面可能会稍微有所不同

1.修改应用程序池启动模式

2.开启对应网站预加载

3.增加配置编辑器,编写默认预加载的请求页面

至此,我们的服务就可以正常的运行啦

Global.asax文件是什么

https://wenku.baidu.com/view/7da87bbb7375a417876f8f30.html

Global.asax文件,有时候叫做ASP.NET应用程序文件,提供了
一种在一个中心位置响应应用程序级或模块级事件的方法。你可以使
用这个文件实现应用程序安全性以及其它一.些任务。下面让我们详细
看一下如何在应用程序开发工作中使用这个文件。

Global.asax位于应用程序根目录下。虽然Visual Studio .NE
T会自动插入这个文件到所有的ASP.NET 项目中,但是它实际上
是一个可选文件。删除它不会出问题一-当然是在你没有使用它的情
况下。.asax 文件扩展名指出它是一个应用程序文件,而不是一个
使用aspx的ASP.NET文 件。

Global.asax文件被配置为任何(通过URL的)直接HTTP
请求都被自动拒绝,所以用户不能下载或查看其内容。ASP.NET页
面框架能够自动识别出对Global.asax文件所做的任何更改。在G
lobal.asax被更改后ASP.NET页面框架会重新启动应用程序,包
括关闭所有的浏览器会话,去除所有状态信息,并重新启动应用程序
域。

Global.asax文件继承自HttpApplication类,它维护一个Htt
pApplication对象池,并在需要时将对象池中的对象分配给应用程
序。Global.asax 文件包含以下事件:

Application_ Init: 在应用程序被实例化或第一次被调用时,
该事件被触发。对于所有的HttpApplication对象实例,它都会被
调用。

Application_ Disposed: 在应用程序被销毁之前触发。这
是清除以前所用资源的理想位置。

posted @ 2022-05-19 18:35  yinghualeihenmei  阅读(396)  评论(0编辑  收藏  举报