.NET Core 中的短运行后台任务 [英] Short running background task in .NET Core
问题描述
我刚刚发现了 IHostedService
和 .NET Core 2.1 BackgroundService
类.我认为想法很棒.文档.
I just discovered IHostedService
and .NET Core 2.1 BackgroundService
class. I think idea is awesome. Documentation.
我发现的所有示例都用于长时间运行的任务(直到应用程序死亡).但我需要它的时间很短.正确的做法是什么?
All examples I found are used for long running tasks (until application die). But I need it for short time. Which is the correct way of doing it?
例如:
我想在应用程序启动后执行一些查询(它们大约需要 10 秒).并且仅当处于开发模式时.我不想延迟应用程序启动,所以 IHostedService
似乎是个好方法.我不能使用 Task.Factory.StartNew
,因为我需要依赖注入.
For example:
I want to execute a few queries (they will take approx. 10 seconds) after application starts. And only if in development mode. I do not want to delay application startup so IHostedService
seems good approach. I can not use Task.Factory.StartNew
, because I need dependency injection.
目前我是这样做的:
public class UpdateTranslatesBackgroundService: BackgroundService
{
private readonly MyService _service;
public UpdateTranslatesBackgroundService(MyService service)
{
//MService injects DbContext, IConfiguration, IMemoryCache, ...
this._service = service;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await ...
}
}
启动:
public static IServiceProvider Build(IServiceCollection services, ...)
{
//.....
if (hostingEnvironment.IsDevelopment())
services.AddSingleton<IHostedService, UpdateTranslatesBackgroundService>();
//.....
}
但这似乎有点矫枉过正.是吗?注册单例(这意味着类在应用程序存在时存在).我不需要这个.只需创建类,运行方法,处理类.全部在后台任务中.
But this seems overkill. Is it? Register singleton (that means class exists while application lives). I don't need this. Just create class, run method, dispose class. All in background task.
推荐答案
没有必要为此做任何魔法.
There's no need to do any magic for this to work.
简单地说:
- 在
ConfigureServices
中注册你需要运行的服务 - 在
Configure
中解析你需要的实例并运行它. - 为避免阻塞,请使用
Task.Run
.
- Register the service you need to run in
ConfigureServices
- Resolve the instance you need in
Configure
and run it. - To avoid blocking, use
Task.Run
.
您必须注册该实例,否则依赖注入将不起作用.这是不可避免的;如果您需要 DI,那么您必须这样做.
You must register the instance, or dependency injection won't work. That's unavoidable; if you need DI, then you have to do it.
除此之外,按照您的要求做就很简单了,就像这样:
Beyond that, it's trivial to do what you ask, like this:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddTransient<MyTasks>(); // <--- This
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
// Blocking
app.ApplicationServices.GetRequiredService<MyTasks>().Execute();
// Non-blocking
Task.Run(() => { app.ApplicationServices.GetRequiredService<MyTasks>().Execute(); });
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
}
}
public class MyTasks
{
private readonly ILogger _logger;
public MyTasks(ILogger<MyTasks> logger)
{
_logger = logger;
}
public void Execute()
{
_logger.LogInformation("Hello World");
}
}
BackgroundService
专门存在于长时间运行的进程中;如果是一次,请不要使用它.
BackgroundService
exists specifically for long running processes; if it's a once of, don't use it.
这篇关于.NET Core 中的短运行后台任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!