Core 2.0 IServiceCollection 缺少 AddHostedService?

尝试使用:


启动.cs


public void ConfigureServices(IServiceCollection services) {

  services.AddHostedService<LifetimeEvents>();

    .

    .

    .

}

LifeTimeEvents 类从 IHostedService 继承。我收到此错误:


'IServiceCollection' does not contain a definition for 'AddHostedService' and no extension method 'AddHostedService' accepting a first argument of type 'IServiceCollection' could be found (are you missing a using directive or an assembly reference?)

我似乎找不到要使用的正确命名空间或要包含的 nuget 包以使其正常工作,但它在 .NET Core 2.1 中开箱即用,这在 .NET Core 2.0 中是否不可用?有什么办法让它工作吗?


更新:


作为一种解决方法,我将代码更改为使用:


启动.cs


public void ConfigureServices(IServiceCollection services) {

  services.AddSingleton<LifetimeEvents>();

    .

    .

    .

}


public void Configure(IApplicationBuilder appBuilder, IHostingEnvironment envHost, LifetimeEvents appEvents)  {

  appEvents.StartAsync(new CancellationToken(false));

    .

    .

    .

}

这似乎已经完成了这项工作。没有回答我最初的问题,我不确定它是多么“最佳实践”,但它确实让我开始重构这个 .NET Core 2.0 应用程序。


炎炎设计
浏览 255回答 2
2回答

慕妹3242003

这只是在 .NET Core 2.0 中不可用吗?ServiceCollectionHostedServiceExtensions.AddHostedService(IServiceCollection) 方法如 API 参考中所示适用于ASP.NET Core2.1但是源代码可以在 GitHub 上找到。您可以轻松地在那里查看并将本地版本复制到您的 2.0 项目namespace Microsoft.Extensions.DependencyInjection{&nbsp; &nbsp; public static class ServiceCollectionHostedServiceExtensions&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; /// <summary>&nbsp; &nbsp; &nbsp; &nbsp; /// Add an <see cref="IHostedService"/> registration for the given type.&nbsp; &nbsp; &nbsp; &nbsp; /// </summary>&nbsp; &nbsp; &nbsp; &nbsp; /// <typeparam name="THostedService">An <see cref="IHostedService"/> to register.</typeparam>&nbsp; &nbsp; &nbsp; &nbsp; /// <param name="services">The <see cref="IServiceCollection"/> to register with.</param>&nbsp; &nbsp; &nbsp; &nbsp; /// <returns>The original <see cref="IServiceCollection"/>.</returns>&nbsp; &nbsp; &nbsp; &nbsp; public static IServiceCollection AddHostedService<THostedService>(this IServiceCollection services)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; where THostedService : class, IHostedService&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; => services.AddTransient<IHostedService, THostedService>();&nbsp; &nbsp; }}理想情况下,您可以将项目更新到 2.1,以便扩展可用。

收到一只叮咚

我相信你正在寻找这个https://blogs.msdn.microsoft.com/cesardelatorre/2017/11/18/implementing-background-tasks-in-microservices-with-ihostedservice-and-the-backgroundservice-class-net-core-2-x/我对自己做了一个 2 小时自称获奖的黑客马拉松,以了解这一点。https://github.com/nixxholas/nautilus您可以在此处参考注入并从那里实现摘要。许多 MVC 项目并不真正需要操作持久的后台任务。这就是为什么您看不到它们通过模板融入新项目的原因。最好为开发人员提供一个可以点击并继续使用的界面。此外,关于为此类后台任务打开该套接字连接,我还没有为此建立解决方案。据我所知/所做的,我只能将有效负载广播到连接到我自己的 socketmanager 的客户端,所以你必须在别处寻找。如果 IHostedService 中有任何关于 websocket 的信息,我肯定会发出哔哔声。好吧,无论如何,这就是发生的事情。把它放在你的项目中的某个地方,它更像是一个让你重载以创建自己的任务的界面/// Copyright(c) .NET Foundation.Licensed under the Apache License, Version 2.0.&nbsp; &nbsp; /// <summary>&nbsp; &nbsp; /// Base class for implementing a long running <see cref="IHostedService"/>.&nbsp; &nbsp; /// </summary>&nbsp; &nbsp; public abstract class BackgroundService : IHostedService, IDisposable&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; protected readonly IServiceScopeFactory _scopeFactory;&nbsp; &nbsp; &nbsp; &nbsp; private Task _executingTask;&nbsp; &nbsp; &nbsp; &nbsp; private readonly CancellationTokenSource _stoppingCts =&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;new CancellationTokenSource();&nbsp; &nbsp; &nbsp; &nbsp; public BackgroundService(IServiceScopeFactory scopeFactory) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _scopeFactory = scopeFactory;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; protected abstract Task ExecuteAsync(CancellationToken stoppingToken);&nbsp; &nbsp; &nbsp; &nbsp; public virtual Task StartAsync(CancellationToken cancellationToken)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Store the task we're executing&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _executingTask = ExecuteAsync(_stoppingCts.Token);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // If the task is completed then return it,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // this will bubble cancellation and failure to the caller&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (_executingTask.IsCompleted)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _executingTask;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Otherwise it's running&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Task.CompletedTask;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public virtual async Task StopAsync(CancellationToken cancellationToken)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Stop called without start&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (_executingTask == null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Signal cancellation to the executing method&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _stoppingCts.Cancel();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; finally&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Wait until the task completes or the stop token triggers&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cancellationToken));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public virtual void Dispose()&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _stoppingCts.Cancel();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }这是您实际使用它的方法public class IncomingEthTxService : BackgroundService&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public IncomingEthTxService(IServiceScopeFactory scopeFactory) : base(scopeFactory)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; protected override async Task ExecuteAsync(CancellationToken stoppingToken)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (!stoppingToken.IsCancellationRequested)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; using (var scope = _scopeFactory.CreateScope())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var dbContext = scope.ServiceProvider.GetRequiredService<NautilusDbContext>();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine("[IncomingEthTxService] Service is Running");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Run something&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await Task.Delay(5, stoppingToken);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }如果你注意到了,那里有一个奖金。您必须使用服务范围才能访问数据库操作,因为它是单例的。注入你的服务// Background Service Dependencies&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; services.AddSingleton<IHostedService, IncomingEthTxService>();
打开App,查看更多内容
随时随地看视频慕课网APP