我刚刚发现了 IHostedService
和 .NET Core 2.1 BackgroundService
类。我认为这个想法很棒。 Documentation .
我找到的所有示例都用于长时间运行的任务(直到应用程序死掉)。 但我需要它的时间很短。哪种方法正确?
例如:
我想在应用程序启动后执行一些查询(它们将花费大约 10 秒)。并且仅当处于开发模式时。我不想延迟应用程序启动,所以 IHostedService
似乎是个好方法。我不能使用 Task.Factory.StartNew
,因为我需要依赖注入(inject)。
目前我是这样做的:
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>();
//.....
}
但这似乎有些矫枉过正。是吗?注册单例(这意味着类在应用程序存在时存在)。我不需要这个。只需创建类、运行方法、处理类。全部在后台任务中。
最佳答案
无需施展任何魔法即可实现。
简单地:
- 在
ConfigureServices
中注册你需要运行的服务 - 在
Configure
中解析你需要的实例并运行。 - 要避免阻塞,请使用
Task.Run
。
您必须注册该实例,否则依赖注入(inject)将不起作用。这是不可避免的;如果您需要 DI,那么您就必须这样做。
除此之外,按照您的要求做是微不足道的,就像这样:
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
存在专门用于长时间运行的进程;如果是一次,请不要使用它。
关于c# - .NET Core 中的短期运行后台任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48321329/