.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 $ c中注册您需要运行的服务$ c>
- 在
配置
中解析所需的实例并运行它。 - 要为避免阻塞,请使用
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
.
您必须注册实例,否则依赖项注入将不起作用。那是不可避免的;
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屋!