在业务场景中经常需要后台服务不停的或定时处理一些任务,这些任务是不需要及时响应请求的。

在 asp.net中会使用windows服务来处理。

在 asp.net core中,可以使用托管服务来实现,托管服务是一个类,具有实现IHostService接口的后台任务逻辑。

导入包

使用NUGET添加Microsoft.Extensions.Hosting包到项目中

 Microsoft.Extensions.Hosting包地址

IHostedService接口

  • 托管服务必须实现IHostedService接口,该接口为主机管理的对象定义了两种方法。

    StartAsync(CancellationToken) - StartAsync包含启动后台任务的逻辑。使用Web主机时,StartAsync在服务器启动并且触发IApplicationLifetime.ApplicationStarted后调用。使用Generic Host时,StartAsync会在ApplicationStarted触发之前调用。

  • StopAsync(CancellationToken) - 在主机执行正常关闭时触发。StopAsync包含结束后台任务的逻辑。实现IDisposable和终结器(析构函数)来处理任何非托管资源。

取消令牌具有默认的五秒超时,以指示关闭过程不再是正常的。在令牌上请求取消时:

应该中止应用正在执行的任何剩余后台操作。

任何调用的方法都StopAsync应该立即返回。

但是,在请求取消后,任务不会被放弃 - 调用者等待所有任务完成。

如果应用程序被意外关闭(例如,应用程序的进程失败),则StopAsync可能无法调用。因此,StopAsync是有可能不会被调用的。

托管服务在应用启动时激活一次,并在应用关闭时正常关闭。为防止异常,最好继承IDispose接口,释放资源

定时后台任务用例

可以写一个托管服务类直接继承IHostedService,和IDisposable接口

 public class MyTimerHostedService : IHostedService, IDisposable
{
private Timer _timer; public Task StartAsync(CancellationToken cancellationToken)
{
Console.WriteLine("启动定时任务托管服务"); _timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(0.5)); return Task.CompletedTask;
} private void DoWork(object state)
{
Console.WriteLine("定时任务处理中");
} public Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Change(Timeout.Infinite, 0);
Console.WriteLine("停止定时任务");
return Task.CompletedTask;
} public void Dispose()
{
// 手动释放定时器
_timer?.Dispose();
}
}

该服务Startup.ConfigureServices使用AddHostedService扩展方法注册:

services.AddHostedService<MyTimerHostedService>();

使用通用主机启动 托管服务

  class Program
{
static void Main(string[] args)
{
var host = new HostBuilder().ConfigureServices((hostContext, services) =>
{
services.AddHostedService<MyTimerHostedService>();
}).Build(); host.Run(); Console.WriteLine("Hello World!");
Console.ReadLine();
}
}

使用后台服务BackgroundService 实现

.NET Core中实现的抽象BackgroundService基类。

// Copyright (c) .NET Foundation. Licensed under the Apache License, Version 2.0.
/// <summary>
/// Base class for implementing a long running <see cref="IHostedService"/>.
/// </summary>
public abstract class BackgroundService : IHostedService, IDisposable
{
private Task _executingTask;
private readonly CancellationTokenSource _stoppingCts =
new CancellationTokenSource(); protected abstract Task ExecuteAsync(CancellationToken stoppingToken); public virtual Task StartAsync(CancellationToken cancellationToken)
{
// Store the task we're executing
_executingTask = ExecuteAsync(_stoppingCts.Token); // If the task is completed then return it,
// this will bubble cancellation and failure to the caller
if (_executingTask.IsCompleted)
{
return _executingTask;
} // Otherwise it's running
return Task.CompletedTask;
} public virtual async Task StopAsync(CancellationToken cancellationToken)
{
// Stop called without start
if (_executingTask == null)
{
return;
} try
{
// Signal cancellation to the executing method
_stoppingCts.Cancel();
}
finally
{
// Wait until the task completes or the stop token triggers
await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite,
cancellationToken));
} } public virtual void Dispose()
{
_stoppingCts.Cancel();
}
}

由于抽象类已经实现了IHostService接口定义的方法,只需要写子类去继承BackgroundService, 在自己的自定义托管服务类中实现ExecuteAsync()方法

 public class MyBackGroundService : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
Console.WriteLine("MyBackGroundService doing"); //延迟500毫秒执行 相当于使用了定时器
await Task.Delay(500, stoppingToken);
}
}
}

在主机中托管服务

class Program
{
static void Main(string[] args)
{
var host = new HostBuilder().ConfigureServices((hostContext, services) =>
{
//services.AddHostedService<MyTimerHostedService>();
services.AddHostedService<MyBackGroundService>();
}).Build(); host.Run(); Console.WriteLine("Hello World!");
Console.ReadLine();
}
}

使用了HostService后极大的方便了后台任务的管理

github源码地址

在asp.net core中使用托管服务实现后台任务的更多相关文章

  1. 第二十二节:Asp.Net Core中使用托管服务实现后台任务

    1. 说明 BackgroundService 是用于实现长时间运行的 IHostedService 的基类,使用程序集:Microsoft.Extensions.Hosting. 2. 实现方式 继 ...

  2. 在ASP.NET Core中创建基于Quartz.NET托管服务轻松实现作业调度

    在这篇文章中,我将介绍如何使用ASP.NET Core托管服务运行Quartz.NET作业.这样的好处是我们可以在应用程序启动和停止时很方便的来控制我们的Job的运行状态.接下来我将演示如何创建一个简 ...

  3. ASP.NET Core 中的那些认证中间件及一些重要知识点

    前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...

  4. Asp.net Core中使用Session

    前言 2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Cor ...

  5. 在ASP.NET Core中使用百度在线编辑器UEditor

    在ASP.NET Core中使用百度在线编辑器UEditor 0x00 起因 最近需要一个在线编辑器,之前听人说过百度的UEditor不错,去官网下了一个.不过服务端只有ASP.NET版的,如果是为了 ...

  6. ASP.NET Core中的依赖注入(1):控制反转(IoC)

    ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...

  7. ASP.NET Core中的依赖注入(2):依赖注入(DI)

    IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...

  8. ASP.NET Core中的依赖注入(3): 服务的注册与提供

    在采用了依赖注入的应用中,我们总是直接利用DI容器直接获取所需的服务实例,换句话说,DI容器起到了一个服务提供者的角色,它能够根据我们提供的服务描述信息提供一个可用的服务对象.ASP.NET Core ...

  9. ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理

    ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...

随机推荐

  1. Unity的赛车游戏实现思路

    unity目前版本实现赛车的技术方案主要有3种: 1.wheelCollider,设置motorTorque.brakeTorque.steerAngle来实现车子的推动和转弯,优点是上手简单,而且很 ...

  2. SQL TRUNCATE TABLE 命令

    SQL TRUNCATE TABLE 命令 SQL TRUNCATE TABLE 命令用于删除现有数据表中的所有数据. 你也可以使用 DROP TABLE 命令来删除整个数据表,不过 DROP TAB ...

  3. JMM内存模型详解(一)

    本文开始死磕JMM(Java内存模型)由于知识点较多,分来写 该文为JMM第一篇 技术往往是枯燥的,本文文字较多 1. JMM是什么? 其实JMM很好理解,我简单的解释一下,在Java多线程中我们经常 ...

  4. linux 目录大小 文件个数 基于文件大小排列显示

    显示硬盘占用空间du -hlsblk 查看指定目录大小du -sh /opt查看各个目录大小du -h --max-depth=1 当前目录的全部文件个数(包含子文件夹的文件)ls -lR | gre ...

  5. CSS布局:元素垂直居中

    CSS布局之元素垂直居中 本文将依次介绍在不同条件下实现垂直居中的多种方法及简单原理 Tip:下文中说的适用场景只是举了几个简单的例子方便读者理解.实际应用场景太复杂,生搬硬套容易出错.最重要的是掌握 ...

  6. Oracle笔记_基础

    1 登录启动 sqlplus / as sysdba #以管理员方式登录 sqlplus 用户名/密码 #本地登录 sqlplus 用户名/密码@//主机IP/实例名(默认orcl) #远程登录 sq ...

  7. TokuDB · 引擎特性 · HybridDB for MySQL高压缩引擎TokuDB 揭秘

    原文出处:阿里云RDS-数据库内核组 HybridDB for MySQL(原名petadata)是面向在线事务(OLTP)和在线分析(OLAP)混合场景的关系型数据库.HybridDB采用一份数据存 ...

  8. NanoPi NEO2 学习笔记 1:安装系统、首次开机和一些设置

    初识NEO2 前几天搞到了一块NanoPi NEO2,A53的核心,512M内存,一个千兆网口,非常小的体积,质量也不错,非常满意,140元的价格可以买到这样一块ARM开发板也是非常划算了,非常适合低 ...

  9. ranger-hdfs 插件组权限测试

    当hdfs文件对外是公开的则该其他用户就算没有配置相关的权限一样可以进行相关的操作.当hdfs文件对外权限是没有开放的,其他用户若需要进行相关操作则需要通过Ranger进行相关权限的配置. 首先  / ...

  10. HDU 6242

    题意略. 思路:这个题的思路非常诡异.由于题目保证存在这样一个圆,那么每个点在这个圆上的概率是1/2,我任选3个点,这3个点都在这个圆上的概率是1 / 8. 不都在这个圆上的概率是7 / 8,在这样选 ...