[英]how do i make a background worker to update a datastore every 5 minutes in asp.net core
I've followed the getting started tutorial and currently have a TODO CRUD app.我遵循了入门教程,目前有一个 TODO CRUD 应用程序。
https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api-mac?view=aspnetcore-2.1 https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api-mac?view=aspnetcore-2.1
I want to add a background worker that updates the todo database every 5 minutes and sets Item 1 to a random value for its Name, and isCompleted properties.我想添加一个后台工作程序,每 5 分钟更新一次待办事项数据库,并将项目 1 设置为其 Name 和 isCompleted 属性的随机值。
This is pretty easy in Java SpringBoot or Elixir's Phoenix... Is there a quick and painless way in c# to do this?这在 Java SpringBoot 或 Elixir's Phoenix 中非常简单......在 c# 中是否有一种快速而轻松的方法来做到这一点?
The doc I found on Microsoft website was from 2012... so I assume there is a more elegant way to do this by now.我在 Microsoft 网站上找到的文档是 2012 年的……所以我认为现在有一种更优雅的方法可以做到这一点。
Edit: I went with DNTScheduler.Core and it was relatively painless to set up.编辑:我使用了 DNTScheduler.Core,设置起来相对轻松。 Followed the exampleApp setup that was on github repo and here is the task i ended up using:
按照github repo上的exampleApp设置,这是我最终使用的任务:
using System;
using System.Threading.Tasks;
using DNTScheduler.Core.Contracts;
using Microsoft.Extensions.Logging;
using myapp.Models;
namespace MyApp.Tasks
{
public class TaskOne : IScheduledTask
{
private readonly ILogger<DoBackupTask> _logger;
private readonly TodoContext _context; // autoinjects since it was added in startup.cs in configure()
public TaskOne(ILogger<DoBackupTask> logger, TodoContext context)
{
_logger = logger;
_context = context;
}
public Task RunAsync()
{
var todo = _context.TodoItems.Find(1);
if (todo == null)
{
return Task.CompletedTask;
}
string[] names = new string[] { "val1", "val2"};
Random r = new Random();
string random_name = names[r.Next(0, names.Length)];
todo.Name = random_name;
_context.TodoItems.Update(todo);
_context.SaveChanges();
_logger.LogInformation("Ran My Task\n\n ");
return Task.CompletedTask;
}
}
}
I would suggest you use Scheduler, there are some packages that can do that, but the best package that I have seen so far is DNTScheduler.Core我建议你使用 Scheduler,有一些包可以做到这一点,但到目前为止我见过的最好的包是DNTScheduler.Core
DNTScheduler.Core is a lightweight ASP.NET Core's background tasks runner and scheduler. DNTScheduler.Core是一个轻量级的 ASP.NET Core 后台任务运行器和调度器。
for more information, you can visit this link有关更多信息,您可以访问此链接
I would argue that the correct answer is wrong if you want to follow the native practice.如果您想遵循本地实践,我会争辩说正确的答案是错误的。
Make use of IHostedService to perform repetitive actions.利用 IHostedService 执行重复操作。
Here's an answer I've written that addresses that.这是我写的一个解决这个问题的答案。
There is a saying i've read somewhere: "If its worth doing, its worth doing right. If its not worth doing right - find something that is."我在某处读到过一句话:“如果值得做,就值得做正确的事情。如果不值得做正确的事情——找点事情做。”
So, as other colleagues already said, web application is not meant to be a container for background processes for reasons already mentioned.因此,正如其他同事已经说过的,由于已经提到的原因,Web 应用程序并不意味着成为后台进程的容器。
Depending on your environment, you'll be much better off using:根据您的环境,您最好使用:
pretty much anything else is looking for trouble when you don't need one.当您不需要任何其他东西时,几乎所有其他东西都在寻找麻烦。
In this sample I Insert a record to my database ( Word-Suggestion-Table in here) every hour using UnitOfWork
and Repository Pattern
.在这个示例中,我每小时使用
UnitOfWork
和Repository Pattern
向我的数据库(此处为 Word-Suggestion-Table)插入一条记录。 No error on Cannot consume scoped service *IUnitOfWork* from singleton
Cannot consume scoped service *IUnitOfWork* from singleton
上没有错误
1- Add work
class and IWork
interface as below: 1- 添加
work
类和IWork
接口如下:
using System.Threading;
using System.Threading.Tasks;
namespace Map118.App.BackgroundTasks
{
public interface IWorker
{
Task DoWork(CancellationToken cancellationToken);
}
}
Work.cs :工作.cs:
using Map118.DataLayer.IRepositories;
using Map118.Models;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Map118.App.BackgroundTasks
{
public class Worker : IWorker
{
private readonly IServiceProvider serviceProvider;
public Worker( IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public async Task DoWork(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using (var scope = serviceProvider.CreateScope())
{
var _unitOfWork = scope.ServiceProvider.GetRequiredService<IUnitOfWork>();
while (!stoppingToken.IsCancellationRequested)
{
WordSuggestion wordSuggestion = new WordSuggestion()
{
word = Guid.NewGuid().ToString(),
};
await _unitOfWork.wordSuggestionRepository.Add(wordSuggestion);
await _unitOfWork.Save();
await Task.Delay(1000 * 3600);
}
}
}
}
}
}
2- Add another class as below: 2- 添加另一个类,如下所示:
using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading.Tasks;
namespace Map118.App.BackgroundTasks
{
public class UserActivitiesCleaner : BackgroundService
{
private readonly IWorker worker;
public UserActivitiesCleaner(IWorker worker)
{
this.worker = worker;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await worker.DoWork(stoppingToken);
}
}
}
3- Add services
to Startup.cs
: 3- 向
Startup.cs
添加services
:
services.AddHostedService<UserActivitiesCleaner>();
services.AddSingleton<IWorker, Worker>();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.