繁体   English   中英

.NET Core 2.0 IServiceCollection缺少AddHostedService?

[英].NET Core 2.0 IServiceCollection missing AddHostedService?

尝试使用:

Startup.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中不可用吗? 有什么办法可以使其正常工作吗?

更新:

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

Startup.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应用程序。

在.NET Core 2.0中不可用吗?

API参考中所示的ServiceCollectionHostedServiceExtensions.AddHostedService(IServiceCollection)方法

适用于
ASP.NET核心
2.1

但是,源代码在GitHub上可用。 您可以在那里轻松地进行检查并将本地版本复制到您的2.0项目中

namespace Microsoft.Extensions.DependencyInjection
{
    public static class ServiceCollectionHostedServiceExtensions
    {
        /// <summary>
        /// Add an <see cref="IHostedService"/> registration for the given type.
        /// </summary>
        /// <typeparam name="THostedService">An <see cref="IHostedService"/> to register.</typeparam>
        /// <param name="services">The <see cref="IServiceCollection"/> to register with.</param>
        /// <returns>The original <see cref="IServiceCollection"/>.</returns>
        public static IServiceCollection AddHostedService<THostedService>(this IServiceCollection services)
            where THostedService : class, IHostedService
            => services.AddTransient<IHostedService, THostedService>();
    }
}

源代码

理想情况下,您可以将项目更新到可用扩展名的2.1。

我相信这是我之前回答过的重复问题。

我应该在哪里开始在ASP.NET Core中执行持久性后台任务?

下面是答案,复制+粘贴。

我相信你正在寻找这个

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项目来运行持久性后台任务。 这就是为什么您看不到通过模板将它们烘焙到新的新项目中的原因。 最好为开发人员提供一个可以点击并继续进行操作的界面。

另外,关于为此类后台任务打开该套接字连接,我尚未为此建立解决方案。 据我了解/了解,我只能将有效负载广播到连接到我自己的套接字管理器的客户端,因此您必须在其他地方查找。 如果IHostedService中有关于websocket的任何内容,我一定会发出蜂鸣声。

好吧,这就是发生的事情。

将其放在项目中的某个地方,它更多的是接口供您重载以创建自己的任务

/// Copyright(c) .NET Foundation.Licensed under the Apache License, Version 2.0.
    /// <summary>
    /// Base class for implementing a long running <see cref="IHostedService"/>.
    /// </summary>
    public abstract class BackgroundService : IHostedService, IDisposable
    {
        protected readonly IServiceScopeFactory _scopeFactory;
        private Task _executingTask;
        private readonly CancellationTokenSource _stoppingCts =
                                                       new CancellationTokenSource();

        public BackgroundService(IServiceScopeFactory scopeFactory) {
            _scopeFactory = scopeFactory;
        }

        protected abstract Task ExecuteAsync(CancellationToken stoppingToken);

        public virtual Task StartAsync(CancellationToken cancellationToken)
        {
            // Store the task we're executing
            _executingTask = ExecuteAsync(_stoppingCts.Token);

            // If the task is completed then return it,
            // this will bubble cancellation and failure to the caller
            if (_executingTask.IsCompleted)
            {
                return _executingTask;
            }

            // Otherwise it's running
            return Task.CompletedTask;
        }

        public virtual async Task StopAsync(CancellationToken cancellationToken)
        {
            // Stop called without start
            if (_executingTask == null)
            {
                return;
            }

            try
            {
                // Signal cancellation to the executing method
                _stoppingCts.Cancel();
            }
            finally
            {
                // Wait until the task completes or the stop token triggers
                await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite,
                                                              cancellationToken));
            }
        }

        public virtual void Dispose()
        {
            _stoppingCts.Cancel();
        }
    }

实际使用方法如下

public class IncomingEthTxService : BackgroundService
    {
        public IncomingEthTxService(IServiceScopeFactory scopeFactory) : base(scopeFactory)
        {
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {

            while (!stoppingToken.IsCancellationRequested)
            {
                using (var scope = _scopeFactory.CreateScope())
                {
                    var dbContext = scope.ServiceProvider.GetRequiredService<NautilusDbContext>();

                    Console.WriteLine("[IncomingEthTxService] Service is Running");

                    // Run something

                    await Task.Delay(5, stoppingToken);
                }
            }
        }
    }

如果您注意到了,那儿就有一笔奖金。 您必须使用servicescope才能访问数据库操作,因为它是单例的。

将您的服务注入

// Background Service Dependencies
            services.AddSingleton<IHostedService, IncomingEthTxService>();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM