在ASP.NET中如何运行后台任务

简介:
+关注继续查看

[原文发表地址] How to run Background Tasks in ASP.NET

[原文发表时间] 2014-08-26

几年前,Phil Haack写了一篇关于ASP.NET中定期后台任务存在的隐患的优秀文章。他指出了一些人们在后台工作时常见的陷阱。您可阅读这篇文章,下面是他帖子里得出的摘要。

  • 在一个线程中,一个与需求不相关的未处理异常将会终止该进程。
  • 如果你在一个Web Farm中运行网站,你大概会以你的应用程序里,试图在同一时间运行同样任务的多个实例结束。
  • 在AppDomain中运行你的网站会因为种种原因而终止,且后台任务也会随之一起终止。

如果你认为你可以自己写一个后台任务,很可能你会进去误区。我并非怀疑你的技术,只能说这太微妙了。而且,你为什么非要这样做呢?

有很多种方式可以让你在后台工作,有很多资源库和选择可利用。

一些ASP.NET应用程序会承载于你的IIS数据中心里,其他的则将承载于在Azure 云上。在我看来,利用率的频谱大致是这样:

  • 通用方法:Hangfire(或者类似的开源资源库)

用于ASP.NET网站上编写后台任务。

一个正规的Azure功能,用来卸载运行于网站之外的后台任务和度量工作量。

快速测量网站后台进程的数量,并 且你需要调度这些机器。

有很多介绍如何使用Azure WebJobs的优秀文章和视频,也有很多介绍工作者角色是如何在可扩展的Azure云服务中工作的文档,但是介绍关于如何承载ASP.NET应用程序和轻松拥有一个后台服务的不多。这里列举了一些。

WebBackgrounder
正如它所说的“WebBackgrounder是一个web-farm,友好的后台任务管理器的概念证明,意味着它仅仅与一个普通的ASP.NET web应用程序协作。”多年来,它的代码没有公开,但是WebBackgrounder NuGet 包已经被下载了大约50万次。

这个项目的目的是处理一个任务,在web应用程序的后台时间间隔管理一个循环的任务。

如果你的ASP.NET应用程序仅仅需要一个后台任务来运行一个基本的预定时间间隔,那么你可能需要基本的WebBackgrounder知识。

using System;
using System.Threading;
using System.Threading.Tasks; 
namespace WebBackgrounder.DemoWeb
{    
    public class SampleJob : Job    
    {        
         public SampleJob(TimeSpan interval, TimeSpan timeout)            
               : base("Sample Job", interval, timeout)        
        {        
        }         
         public override Task Execute()        
         {            
             return new Task(() => Thread.Sleep(3000));
         }
     }
}

建立:QueueBackgroundWorkItem-加入.NET4.5.2
在某种程度上对WebBackgrounder的需产生影响,QueueBackgroundWorkItem作为一个新的API被添加于.NET 4.5.2 中。它不只是一个”Task.Run”,它的功能还有很多:

QBWI预设了一个可以在后台运行的任务,它独立于任何需求。这不同于平常的ASP.NET线程池工作项,ASP.NET自动记录有多少个通过API注册的工作项正在运行,并且ASP.NET运行时会延迟AppDomain的关闭,直到工作项停止执行。

为了保证任务完成,它可以延迟AppDomain关闭长达90秒。如果你在90秒内无法完成,那么你需要一个不同的(更健壮的,更有意义的,进程以外的)技术。

这个API非常简单,使用Func<CancellationToken, Task>。这里有一个从MVC截取的后台工作项例子:

public ActionResult SendEmail([Bind(Include = "Name,Email")] User user)
{    
     if (ModelState.IsValid)
    {       HostingEnvironment.QueueBackgroundWorkItem(ct => SendMailAsync(user.Email));
            return RedirectToAction("Index", "Home");
    }     
  return View(user);
}

FluentScheduler

FluentScheduler 是一个更精密和复杂的调度程序,它有一个(如你所想)流畅的界面。当你的任务运行时你是真正地显式控制。

using FluentScheduler;
public class MyRegistry : Registry
{    
  public MyRegistry()
  {        // Schedule an ITask to run at an interval        
           Schedule<MyTask>().ToRunNow().AndEvery(2).Seconds();
           // Schedule a simple task to run at a specific time
           Schedule(() => Console.WriteLine("Timed Task - Will run every day at 9:15pm: " + DateTime.Now)).ToRunEvery(1).Days().At(21, 15);
           // Schedule a more complex action to run immediately and on an monthly interval
           Schedule(() =>
           {            
              Console.WriteLine("Complex Action Task Starts: " + DateTime.Now);
              Thread.Sleep(1000);
              Console.WriteLine("Complex Action Task Ends: " + DateTime.Now);
           }).ToRunNow().AndEvery(1).Months().OnTheFirst(DayOfWeek.Monday).At(3, 0);
    }
}

FluentScheduler 也接受IoC,而且可以通过执行ItaskFactory界面来注入你喜欢的Dependency Injection tool。

Quartz.NET

Quartz.NET是一个拥有和流行的Java 工作调度框架(几乎)相同的名字的.NET端口。它得到了快速地发展。Quartz有一个IJob界面,只有一个用来执行的

using Quartz;
using Quartz.Impl;
using System; 
namespace ScheduledTaskExample.ScheduledTasks
{    
   public class JobScheduler 
   { 
       public static void Start()
        {
            IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
            scheduler.Start();
            IJobDetail job = JobBuilder.Create<MyJob>().Build();
            ITrigger trigger = TriggerBuilder.Create()
                .WithDailyTimeIntervalSchedule
                  (s =>
                     s.WithIntervalInHours(24)
                    .OnEveryDay()
                    .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(0, 0))
                   )
                  .Build();
             scheduler.ScheduleJob(job, trigger);
        }
    }
}

然后,在你的应用程序开始之前,你可以调用 JobScheduler.Start()。在Mikesdotnetting上面有一篇关于Quartz启动的优秀文章,你可以查阅。

Hangfire

最后但绝对不是最不重要的是,最优秀的(IMHO)组Hangfire 依从 @odinserj。 它是一个ASP.NET中后台工作极好的框架。为了保证可靠性,它甚至被Redis, SQL Server, SQL Azure, MSMQ, 或 RabbitMQ选择为坚强的后盾。

Hangfire的文档编制真的很神奇。每一个开源项目的文件应该像它这样。ASP.NET的文档编制也应该像它这么好。

Hangfire中最佳的功能是它建立了/hangfire 仪表板,向你展示所有预设的,加工中的,成功的和失败的进程。这真是一个很好的附加功能。

image

你可以轻易地把“fire和forget”工作加入队列并且它们是支持持久队列的:

BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget"));

你可以使用延迟…

BackgroundJob.Schedule(() => Console.WriteLine("Delayed"), TimeSpan.FromDays(1));

或者使用大而复杂的CRON风格的循环性任务:

RecurringJob.AddOrUpdate(() => Console.Write("Recurring"), Cron.Daily);

Hangfire是很有趣的。

查阅Hangfire 高亮教程可以看到一些复杂的但容易遵循现实世界的例子。

这是一个丰富的资源系统,可以帮助你完成后台任务。所有这些资源库都是卓越的,开源的,并且是可用作NuGet 包的。

我有遗漏你最喜欢的部分吗?如果有请在评论板中提出来!




本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/p/5725322.html,如需转载请自行联系原作者

相关文章
|
7月前
|
开发框架 JSON 缓存
基于 Debain11 构建 asp.net core 6.x 的基础运行时镜像
此处我们基于 Debian11 的 Linux 发行版,实现目标是编写 Dockerfile 构建 asp.net core 6.x 框架的 runtime 基础镜像。在 Docker 容器化运行环境中,应用程序运行中存在异常情况,此时可以借助一些常用的基础工具方便排查,因此我们需要在 asp.net core 6.x runtime 基础镜像添加 linux 环境常用的...
224 0
基于 Debain11 构建 asp.net core 6.x 的基础运行时镜像
|
10月前
|
开发框架 .NET
技术关于asp运行环境搭建
技术关于asp运行环境搭建
|
开发框架 .NET
ASP.NET Core 3.x Razor视图运行时刷新实时编译
ASP.NET Core 3.x Razor视图运行时刷新实时编译
|
开发框架 安全 前端开发
关于ASP.NET MVC 项目在本地vs运行响应时间过长无法访问时,解决方法!
关于ASP.NET MVC 项目在本地vs运行响应时间过长无法访问时,解决方法!
114 0
关于ASP.NET MVC 项目在本地vs运行响应时间过长无法访问时,解决方法!
|
开发框架 .NET 应用服务中间件
ASP.NET Core : 五.服务是如何加载并运行的, Kestrel、配置与环境
&quot;跨平台&quot;后的ASP.Net Core是如何接收并处理请求的呢? 它的运行和处理机制和之前有什么不同? 本章从&quot;宏观&quot;到&quot;微观&quot;地看一下它的结构以及不同时期都干了些什么. ASP.NET Core 的运行机制: &quot;宏观&quot;的看一下Http请求的处理流程. ASP.NET Core 的配置与运行: 2倍放大后的ASP.NET Core Application, Kestrel服务器、启动与配置 ASP.NET Core 的环境变量.
173 0
ASP.NET Core : 五.服务是如何加载并运行的, Kestrel、配置与环境
|
开发框架 JSON 安全
ASP.NET Core : 五.服务是如何加载并运行的, Kestrel、配置与环境
"跨平台"后的ASP.Net Core是如何接收并处理请求的呢? 它的运行和处理机制和之前有什么不同? 本章从"宏观"到"微观"地看一下它的结构以及不同时期都干了些什么.
380 0
ASP.NET Core : 五.服务是如何加载并运行的, Kestrel、配置与环境
|
.NET C++ 开发框架
ASP.NET CORE下运行CMD命令
ASP.NET CORE下运行CMD命令,用以前的ASP.NET 的命令System.Diagnostics.Process.Start("notepad");这样是可以运行出记事本的, 现在公司的C++大神开发了个EXE,需要放在服务器上,然后当访问服务器上的某个网页的时候就执行这个EXE了。
1752 0
|
.NET 开发框架 数据格式
相关产品
云迁移中心
推荐文章
更多