开源的.NET定时任务组件Hangfire解析

   项目中很多时候都会使用到定时任务这样一个功能需求,在.NET中对于完成定时任务的技术还是不怎么多的,.NET Framework具有“内置”定时器功能,通过System.Timers.Timer类。在使用Timer类需要面对的问题:计时器没有持久化机制;计时器具有不灵活的计划(仅能设置开始时间和重复间隔,没有基于日期,时间等);计时器不使用线程池(每个定时器一个线程);计时器没有真正的管理方案 - 你必须编写自己的机制,以便能够记住,组织和检索任务的名称等。如果需要在.NET实现定时器的功能,可以尝试使用以下这款开源免费的组件Quartz.Net组件。

  上面介绍了两种方式,在这里就介绍另外一种组件,那就是Hangfire组件。

一.Hangfire组件概述

在.NET和.NET Core应用程序中执行后台处理的简单方法。无需Windows服务或单独的进程。由持久存储支持,存储方式有sqlserver、redis,mongodb等等。Hangfire支持所有类型的后台任务 - 短时间运行和长时间运行,CPU密集型和I / O密集型,一次性和周期性。

   1.组件特点:

   2.组件功能:

      上面是对Hangfire组件背景的一些简单介绍,下面我们具体来了解一下Hangfire组件的使用方法。

二.Hangfire组件使用方法介绍

      既然想要学习了解一个组件,当然需要知道是怎么样取使用,如果不能使用,学着也没有什么很大的用处,下面介绍一下Hangfire组件的一些常用方法。

1.ASP.NET MVC设置方式:

public void Configuration(IAppBuilder app)
{
    GlobalConfiguration.Configuration.UseSqlServerStorage("<connection string or its name>");
    app.UseHangfireDashboard();
    app.UseHangfireServer();
}

GlobalConfiguration类是配置Hangfire的首选方式。这是一些方法的入口点,包括来自第三方存储实现或其他扩展的方法。用法很简单,只需Hangfire在应用程序初始化类中包含命名空间,并发现GlobalConfiguration.Configuration属性的扩展方法

   2.控制台设置方式:

 GlobalConfiguration.Configuration
                .UseColouredConsoleLogProvider()                         .UseSqlServerStorage(@"Server=.\sqlexpress;Database=Hangfire.Sample;Trusted_Connection=True;")
                .UseMsmqQueues(@".\Private$\hangfire{0}", "default", "critical");

3.基于队列的任务处理:

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

4.延迟任务执行:

var jobId = BackgroundJob.Schedule(
    () => Console.WriteLine("Delayed!"),
    TimeSpan.FromDays(7));

5.循环任务执行:

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

6.继续在其父作业完成时执行:

BackgroundJob.ContinueWith(
    jobId,
    () => Console.WriteLine("Continuation!"));

7.批处理方法:

var batchId = BatchJob.StartNew(x =>
{
    x.Enqueue(() => Console.WriteLine("Job 1"));
    x.Enqueue(() => Console.WriteLine("Job 2"));
});

8.当父批次中的所有后台作业完成时,批处理继续:

BatchJob.ContinueWith(batchId, x =>
{
    x.Enqueue(() => Console.WriteLine("Last Job"));
});

   9.使用IoC容器:

public  class  ContainerJobActivator  : JobActivator 
{ 
    private  IContainer  _container ;
    public  ContainerJobActivator (IContainer  container )
    { 
        _container  =  container ; 
    }}
    public  override  object  ActivateJob (Type  type )
    { 
        return  _container 。Resolve (type ); 
    } 
}

    在启动Hangfire服务器之前将其注册为当前作业启动器。

var container = new Container();
GlobalConfiguration.Configuration.UseActivator(new ContainerJobActivator(container));
...
app.UseHangfireServer();

      Hangfire将作业保存到持久存储中,并以可靠的方式处理它们。这意味着你可以中止Hangfire工作线程,卸载应用程序域甚至终止进程,工作将被处理。Hangfire将作业标记为已完成,只有当代码的最后一行执行,并知道作业可能会失败,最后一行。它包含不同的自动重试功能,可以处理代码中的存储错误或错误。

三.Hangfire组件核心对象解析

   上面介绍了Hangfire组件的常用方法,Hangfire组件的功能非常多,这里就做介绍了,有兴趣可以去官网进行查看api。下面介绍一下Hangfire组件的一些核心对象,初探Hangfire组件深层次的问题。

 1.RecurringJob.AddOrUpdate():

 public static void AddOrUpdate(
            Expression<Action> methodCall,
            string cronExpression,
            TimeZoneInfo timeZone = null,
            string queue = EnqueuedState.DefaultQueue)
        {
            var job = Job.FromExpression(methodCall);
            var id = GetRecurringJobId(job);

            Instance.Value.AddOrUpdate(id, job, cronExpression, timeZone ?? TimeZoneInfo.Utc, queue);
        }

   该方法用于定期作业在指定的CRON计划上触发多次。该方法具有16个重载,Job.FromExpression(methodCall);用于获取基于Job类的新实例给定的方法调用的表达式树。GetRecurringJobId(job)方法根据Job对象获取对应的JobID。

2.BackgroundJob.Enqueue():

public static string Enqueue([NotNull, InstantHandle] Expression<Action> methodCall)
        {
            var client = ClientFactory();
            return client.Enqueue(methodCall);
        }

   该方法基于给定的方法调用表达式创建一个新的fire-and-forget作业。该方法接受一个参数,表示将被编组到服务器的方法调用表达式。接下来我们看一下var client = ClientFactory();方法的具体实现

internal static Func<IBackgroundJobClient> ClientFactory
        {
            get
            {
                lock (ClientFactoryLock)
                {
                    return _clientFactory ?? DefaultFactory;
                }
            }
            set
            {
                lock (ClientFactoryLock)
                {
                    _clientFactory = value;
                }
            }
        }

   该属性定义了一个Func<IBackgroundJobClient>的泛型委托。该属性是一个可读可写的操作,对ClientFactoryLock加锁,确保不发生死锁情况。

四.总结

    上面简单的介绍了Hangfire组件的背景和一些简单的应用,也着重的介绍了一些对象。这个组件的功能很强大,需要了解的地方也较多,这一篇文章不可能全部介绍,用做抛砖引玉的作用。在这里吐槽一句,微软最近技术发展太快,很多技术还没有来得及发展,就有新的技术出来,让我们这些底层的人着实难受,事物发展有规律,不是以前缺的东西可以在很短的时间就可以补上,还是需要留下足够的空间。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏张善友的专栏

Visual Studio 2013 Ultimate的可视化代码功能

可视化和了解代码综合了如何使用visual studio可视化代码来帮助理解代码: 理解代码和代码之间的关系:(1)Code Map(2)Dependency ...

1836
来自专栏张善友的专栏

.NET的垃圾回收器

后台垃圾回收器(GC),.NET 4.5服务器应用程序中会默认开启。 在32位的操作系统下,.NET堆大约是2GB。而使用64位的操作系统,微软认为使用10GB...

1647
来自专栏林德熙的博客

win10 uwp 萤火虫效果 安装 win2d创建界面后台的方法核心代码

本文在Nukepayload2指导下,使用他的思想用C#写出来。 本文告诉大家,如何使用 win2d 做出萤火虫效果。

431
来自专栏代码GG之家

自定义View(一)

自定义View 需求场景:当系统默认的view不能满足您的优(qi)美(pa)界面 要求时候,自定义view则进入您的视野,来满足您的客制化。 那么我们这节开车...

1746
来自专栏鹅厂优文

C# 是如何执行的

为什么 Unity3D 可以运行 C#,C# 和 Mono 是什么关系,Mono 和 .Net Framework 又是什么关系?我们深入的来聊一聊这个话题!

6059
来自专栏韩东吉的Unity杂货铺

零基础入门 27:加载Loading的制作和使用

今天要给大家说的是一个游戏中很常见的东西,想必大家也都不会陌生,那就是加载的Loading,俗称游戏里的小菊花。

873
来自专栏张善友的专栏

依赖注入容器Autofac

在.NET上现在存在许多的依赖注入容器, 我也在实践中使用过Castle Windsor、StructureMap、Autofac 、Unity。这些容器的简要...

2159
来自专栏草根专栏

使用静态基类方案让 ASP.NET Core 实现遵循 HATEOAS Restful Web API

Hypermedia As The Engine Of Application State (HATEOAS) HATEOAS(Hypermedia as t...

3865
来自专栏函数式编程语言及工具

Akka(20): Stream:异步运算,压力缓冲-Async, batching backpressure and buffering

   akka-stream原则上是一种推式(push-model)的数据流。push-model和pull-model的区别在于它们解决问题倾向性:push模...

2307
来自专栏张善友的专栏

使用Metrics.NET 构建 ASP.NET MVC 应用程序的性能指标

通常我们需要监测ASP.NET MVC 或 Web API 的应用程序的性能时,通常采用的是自定义性能计数器,性能计数器会引发无休止的运维问题(损坏的计数器、权...

1858

扫码关注云+社区