当前位置:首页 » 《休闲阅读》 » 正文

Asp.net core Webapi 如何执行定时任务?

12 人参与  2024年04月16日 14:09  分类 : 《休闲阅读》  评论

点击全文阅读


在这里插入图片描述

前言

在计算机系统中,定时执行一些后台任务是很常见的场景,比如定时发送邮件、备份数据等等。

那么,.NET 技术如何通过编程灵活地实现项目里复杂的自定义任务呢?

如果是 Windows 生态,通常来说,可以有这些方式:

编写一个程序,通过 Windows 内置的任务计划来定时执行。编写一个程序,通过 Windows 内置的 Services 来定时执行。编写一个定时循环执行任务的程序,在 Windows 系统启动时配置为自动执行。
……

但是,如果是一个中小型的 Web 应用系统,这些方法方式就显得不太合适。**Asp.net core Webapi 有没有办法执行定时任务呢?**答案是有的,Asp.net core Webapi 可以通过常驻后台的托管服务来执行定时任务。

本文是 Asp.net core Webapi 运行一个常驻后台并从数据库中导出数据的托管服务的例子,写出来供大家指点,在讨论过程中共同提高水平。

Step By Step 实现步骤

创建一个 asp.net core webapi 项目从 Nuget 安装以下包

Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Relational
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools

打开 appsettings.json 并添加数据库连接字符串,如:
{  "Logging": {"LogLevel": {  "Default": "Information",  "Microsoft.AspNetCore": "Warning"}  },  "AllowedHosts": "*",  "ConnectionStrings": {"Default": "Server=(localdb)\\mssqllocaldb;Database=IdentityTestDB;Trusted_Connection=True;MultipleActiveResultSets=true"  }}
添加一个继承于 IdentityUser 的 User 类
using Microsoft.AspNetCore.Identity;public class User: IdentityUser<long>{public DateTime CreationTime { get; set; }public string? NickName { get; set; }}
添加一个继承于 IdentityRole 的 Role 类
using Microsoft.AspNetCore.Identity;public class Role: IdentityRole<long>{}
创建数据库上下文
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;using Microsoft.EntityFrameworkCore;public class TestDbContext: IdentityDbContext<User, Role, long>{public TestDbContext(DbContextOptions<TestDbContext> options):base(options){}protected override void OnModelCreating(ModelBuilder builder){base.OnModelCreating(builder);builder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);}}
创建一个 ExplortStatisticBgService 类并继承 BackgroundService,这是托管服务类
using Microsoft.EntityFrameworkCore;using System.Text;public class ExplortStatisticBgService : BackgroundService{private readonly TestDbContext ctx;private readonly ILogger<ExplortStatisticBgService> logger;private readonly IServiceScope serviceScope;/// <summary>/// 在构造方法注入IServiceScopeFactory服务,/// 用来创建IServiceScope对象,/// 这样就可以通过IServiceScope来创建短生命周期的服务了/// </summary>/// <param name="scopeFactory"></param>public ExplortStatisticBgService(IServiceScopeFactory scopeFactory){this.serviceScope = scopeFactory.CreateScope();var sp = serviceScope.ServiceProvider;this.ctx = sp.GetRequiredService<TestDbContext>();this.logger = sp.GetRequiredService<ILogger<ExplortStatisticBgService>>();  }protected override async Task ExecuteAsync(CancellationToken stoppingToken){// 用 while 循环实现服务常驻while (!stoppingToken.IsCancellationRequested){// 用 try...catch 捕捉异常记录错误信息并避免方法退出try{// 这里实现每隔5秒从数据库中导出数据// 更复杂的配置可以用第三方开源的框架await DoExecuteAsync();await Task.Delay(5000);}catch (Exception ex){logger.LogError(ex, "获取用户统计数据失败");await Task.Delay(1000);}}}private async Task DoExecuteAsync(){var items = ctx.Users.AsNoTracking().GroupBy(u => u.CreationTime.Date).Select(e => new { Date = e.Key,Count = e.Count()});StringBuilder sb = new StringBuilder(1024);sb.AppendLine($"Date: {DateTime.Now}");foreach (var item in items){sb.Append(item.Date).AppendLine($": {item.Count}");}await File.WriteAllTextAsync("d:/1.txt", sb.ToString());logger.LogInformation($"导出完成");}/// <summary>/// IServiceScope 需要释放/// 所以重写 Dispose 方法/// </summary>public override void Dispose(){base.Dispose();serviceScope.Dispose();}}
打开 Program.cs,注入托管服务等,看代码的注释
using Microsoft.AspNetCore.Identity;using Microsoft.EntityFrameworkCore;var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddControllers();// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbucklebuilder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();IServiceCollection services = builder.Services;// 注册托管服务services.AddHostedService<ExplortStatisticBgService>();// 注入数据库上下文services.AddDbContext<TestDbContext>(options => {string connStr = builder.Configuration.GetConnectionString("Default")!;options.UseSqlServer(connStr);});// 数据保护服务注入// ----数据保护提供了一个简单、基于非对称加密改进的加密API用于确保Web应用敏感数据的安全存储// ----不需要开发人员自行生成密钥,它会根据当前应用的运行环境,生成该应用独有的一个私钥services.AddDataProtection();// 注入 Identity 框架的一些重要的基础配置// 如果没有这个,下面的注入 UserManager 等服务会有问题,程序无法编译services.AddIdentityCore<User>(options =>{options.Password.RequireDigit = false;options.Password.RequireLowercase = false;options.Password.RequireNonAlphanumeric = false;options.Password.RequireUppercase = false;options.Password.RequiredLength = 6;options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;options.Tokens.EmailConfirmationTokenProvider = TokenOptions.DefaultEmailProvider;});// 注入 UserManager、RoleManager 等Identity 框架服务var idBuilder = new IdentityBuilder(typeof(User), typeof(Role), services);idBuilder.AddEntityFrameworkStores<TestDbContext>().AddDefaultTokenProviders().AddRoleManager<RoleManager<Role>>().AddUserManager<UserManager<User>>();var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){app.UseSwagger();app.UseSwaggerUI();}app.UseHttpsRedirection();app.UseAuthorization();app.MapControllers();app.Run();``
Ctrl+F5 运行项目,不做任何操作,托管程序会自动导出数据

扩展

托管服务在后台运行,通过它可以实现在很多事情,比如:

监控消息队列,当有数据进入消息队列就处理。再如每隔10s把A数据库中的数据同步到B数据库中… 等等

点击全文阅读


本文链接:http://m.zhangshiyu.com/post/96045.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 小说江诗云路明哲小说已更新+番外篇章(年少的爱终将散去)纯净阅读
  • 真千金伪装大学生在自家公司实习让狗爬后一口气看完_宋氏小林小姑娘高分神作_小说后续在线阅读_无删减免费完结_
  • 萧逸尘,楚璃,叶紫嫣爱恨决绝,此生不见番外(爱恨决绝,此生不见)TXT+后续+结局在线阅读
  • 假千金要交换人生?我抱着空间做首富爽文_苏木青赵景城虐心反转_小说后续在线阅读_无删减免费完结_
  • 温时雨谢远之续集(清风难渡无缘人)全本完整免费版_起点章节+后续(温时雨谢远之)
  • 订婚两个月后,未婚夫要摆脱包办婚姻精心打造_肖明宝宝宾客故事会_小说后续在线阅读_无删减免费完结_
  • 霍景琛,苏晚,林深昔年请深如海,终不敌薄凉附加(霍景琛,苏晚,林深)(昔年请深如海,终不敌薄凉)全本浏览阅读连载中
  • 新章速递汤安甯,白子奕,汤贝贝是什么小说(结婚十年,回归家庭的老婆在外有二胎了)完本阅读无广告(结婚十年,回归家庭的老婆在外有二胎了)
  • 娇牛马导师偷我论文99篇成功升博导,我让他牢底坐穿精校文本_周老师师姐师兄爽文_小说后续在线阅读_无删减免费完结_
  • 独家顾宇,罗薇:结局+番外精编之作(资助生装阔气,我可不参加)电子书畅享阅读
  • 宗门全员重生,小师妹摆烂不干了(君拂君芙蓉)_宗门全员重生,小师妹摆烂不干了
  • 成了高考状元后,我倒欠两百万完结txt_阿姨叶青江安TOP10_小说后续在线阅读_无删减免费完结_

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1