Asp.net core Webapi 如何执行定时任务?
1.看看 Asp.net core Webapi 项目如何优雅地使用分布式缓存
2.Asp.net core Webapi 如何执行定时任务?
3.试试这 6 个小技巧,提升 EF Core 性能4.C# 完美实现物联网 MQTT 数据通信5.Asp.net Webapi 的 Post 方法不能把参数加到 URL 中?试试这样写6.如何在 ASP.NET Core Web API 方法执行前后 “偷偷“ 作一些 “坏“ 事?初识 ActionFilterAttribute7.在 ASP.NET Core Web API 中使用异常筛选器捕获和统一处理异常8.操作筛选器的 1 个应用实例:自动启用事务9.并发请求太多,服务器崩溃了?试试使用 ASP.NET Core Web API 操作筛选器对请求进行限流10.一个简单的 ASP.NET Core 依赖注入例子,提高代码的可维护性和可扩展性11.由一个业务需求引发的对 ASP.NET 全局变量的调研及结果12.服务注册自治,降低 ASP.NET Core Web API 依赖注入的耦合度和复杂度13.ASP.NET Core 标识(Identity)框架系列(一):如何使用 ASP.NET Core 标识(Identity)框架创建用户和角色?14.ASP.NET Core 标识(Identity)框架系列(二):使用标识(Identity)框架生成 JWT Token15.ASP.NET Core 标识(Identity)框架系列(三):在 ASP.NET Core Web API 项目中使用标识(Identity)框架进行身份验证16.ASP.NET Core 标识(Identity)框架系列(四):闲聊 JWT 的缺点,和一些解决思路前言
在计算机系统中,定时执行一些后台任务是很常见的场景,比如定时发送邮件、备份数据等等。
那么,.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/swashbuckle builder.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数据库中
- ...... 等等
合集:
.NET
分类:
C#
, Asp.NET Core
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)