在 C# .NET Web 应用程序中每天安排任务的正确方法

Posted

技术标签:

【中文标题】在 C# .NET Web 应用程序中每天安排任务的正确方法【英文标题】:Proper way to schedule a task daily in C# .NET web application 【发布时间】:2016-11-21 06:15:08 【问题描述】:

我有一个 ASP.NET MVC 应用程序,可让用户存储视频和照片等媒体。

该应用程序还允许用户删除存储在服务器中的那些媒体。为此,我想实现一个“两个步骤”过程,其中首先(选择要删除介质时),数据库中的媒体条目将获得一个时间戳,指示必须在一段时间内删除条目(例如一个月);如果那个时间戳在那段时间内没有被删除,应该有一个每天执行的计划方法,并检查媒体条目是否有足够老的时间戳可以删除。

我的问题是关于调度程序的: 我读到有一些框架,如 FluentScheduler 或 Quartz.NET 来实现这类工作。由于应用程序是部署在 IIS 中的 Web 应用程序,恐怕没有使用正确的方式、框架或方法来实现它。由于 IIS 可以随时关闭我的应用程序,并且由于计划的方法将执行对 DB 和 IO 文件系统的写入以删除 db 条目和物理文件,因此该方法完全执行或不执行对我来说至关重要all,以保持 db 与存储在 hd 的文件一致。

我的第一个赌注是 FluentScheduler,但我需要知道使用这样的框架是否是最佳解决方案。

我知道 *** 不欢迎这类问题。这不是意见问题,我只是想阅读解决方案并选择最符合我要求的解决方案。

下面是调度方法中的某种伪代码:

using(ViewMediaDBUnitOfWork uw = new ViewMediaDBUnitOfWork())
        
            var today = DateTime.Now.Date;

            List<Media> mediaToDelete = uw.MediaRepository.Get(m => (m.ToDelete - today).value.Days > 30);
            mediaToDelete.ForEach(m =>
            
                try
                
                    //Deletes from DB
                    uw.MediaRepository.Delete(m);
                    //Deletes the file
                    File.Delete(m.Path);
                    //If everything is ok, savechanges
                    uw.MediaRepository.SaveChanges();
                
                catch(Exception e)
                
                    LogManager.GetCurrentClassLogger().Error("Error deleting. " + m.Path, e);
                                    
            );
        

【问题讨论】:

我不会在 Web 应用程序中安排任务。我会创建一个单独的应用程序,由服务器上的任务调度程序运行以进行清理。 能否请您扩展您的答案?如何在服务器上实现任务调度程序...或者可能是您所想的更多信息的链接。 我说的只是标准的 Windows 服务器任务调度程序:technet.microsoft.com/en-us/library/cc748993(v=ws.11).aspx 【参考方案1】:

听起来您最好创建一个单独的服务来处理时间戳记录的删除,而不是尝试将其捆绑到您现有的应用程序中。

作为一种非常快速的解决方案,创建a Powershell script 将花费大约 10 分钟,该a Powershell script 将运行 SQL 查询,删除时间戳 > x 日期的数据。

然后您可以schedule this script 每天跑步。这比希望 IIS 工作池线程仍然在运行要可靠得多。

还有其他一些方法,例如 SSIS,但可能比您需要的更复杂。

【讨论】:

【参考方案2】:

如果您要安排一项任务,至少您希望至少在 HostingEnvironment.QueueBackgroundWorkItem 的上下文中执行它。这会将您的工作注册到 ASP.NET 运行时。虽然有警告。当 ASP.NET 因任何原因回收时,它会通知后台工作(通过设置 CancellationToken),然后它将等待指定的时间段(我认为是 30 秒)以完成工作。如果后台工作未在该时间范围内完成,则该工作将消失。

FluentScheduler 和 Quartz 是很好的框架,但如果可以避免(出于上述原因),则应避免在 ASP.NET 应用程序的上下文中调度工作。您可以创建一个使用这些框架在您的应用程序之外安排作业/重复任务的服务。

但是,更可靠的选择是使用Hangfire 之类的技术/框架,它与某种可靠的存储(例如 SQL Server、Redis 或 MSMQ)结合使用。

Hangfire 是一个开源框架,可帮助您创建、处理 并管理您的后台作业,即你不想放的操作 在您的请求处理管道中

【讨论】:

以上是关于在 C# .NET Web 应用程序中每天安排任务的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

Celerybeat 每天两次在不同时间安排任务

如何安排任务调用 gRPC 方法?

安排任务在两个日期之间每天运行两次

安排任务每天在 eJabberd 服务器上运行?

安排每天运行 2 次的任务 [重复]

使用 Laravel 每天安排两次任务