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

Proper way to schedule a task daily in C# .NET web application

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

该应用程序还允许用户删除存储在服务器中的那些媒体。为此,我想实现一个 "two steps" 过程,其中首先(当媒体被 select 删除时),数据库中的媒体条目将获得一个时间戳,指示该条目必须在某个时间(例如一个月)被删除;如果那个时间戳在那个时候没有被删除,应该有一个每天执行的计划方法,并检查媒体条目是否有足够大的时间戳来删除。

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

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

我知道 Whosebug 不欢迎这类问题。这不是一个意见问题,我只想阅读解决方案和 select 最符合我要求的解决方案。

这是计划方法中的某种伪代码:

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);
                }                    
            });
        }

如果您要安排一项任务,至少您希望至少在 HostingEnvironment.QueueBackgroundWorkItem 的范围内进行。这会将您的工作注册到 ASP.NET 运行时。尽管有警告。当 ASP.NET 出于某种原因回收时,它会通知后台工作(通过设置 CancellationToken),然后等待指定的时间段(我认为是 30 秒)让工作完成。如果后台工作没有在那个时间范围内完成,工作就会消失。

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

但是,更稳健的选择是使用像 Hangfire 这样的技术/框架,它与某种可靠的存储结合使用,例如 SQL 服务器、Redis 或 MSMQ。

Hangfire is an open-source framework that helps you to create, process and manage your background jobs, i.e. operations you don't want to put in your request processing pipeline.

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

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

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

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