标签: asp.net-core-hosted-services

在ASP.NET Core中注册HostedService的正确方法.AddHostedService vs AddSingleton

在ASP.NET Core 2.1中注册自定义托管服务的正确方法是什么?例如,我已经定制托管源自服务BackgroundService命名MyHostedService.我该如何注册?

public IServiceProvider ConfigureServices(IServiceCollection services)
{           
    //...
    services.AddSingleton<IHostedService, MyHostedService>();
}
Run Code Online (Sandbox Code Playgroud)

要么

public IServiceProvider ConfigureServices(IServiceCollection services)
{           
    //...
    services.AddHostedService<MyHostedService>();
}
Run Code Online (Sandbox Code Playgroud)

在这里我们可以看到第一种情况,但这里有第二种情况.

这些方法是否相同?

c# .net-core asp.net-core asp.net-core-2.1 asp.net-core-hosted-services

20
推荐指数
3
解决办法
1万
查看次数

在 ASP.NET Core 中每 5 分钟运行一次异步托管服务

后台服务的ASP.NET Core文档显示了许多实现示例。

有一个在计时器上启动服务的示例,尽管它是同步的。还有另一个异步示例,用于启动具有范围依赖项的服务。

我需要同时执行这两项操作:每 5 分钟启动一个服务,并且它具有范围内的依赖项。没有这样的例子。

我结合了这两个示例,但我不确定使用Timerasync 的安全方法TimerCallback

例如

public class MyScheduler : IHostedService
{
  private Timer? _timer;
  private readonly IServiceScopeFactory _serviceScopeFactory;

  public MyScheduler(IServiceScopeFactory serviceScopeFactory) => _serviceScopeFactory = serviceScopeFactory;

  public void Dispose() => _timer?.Dispose();

  public Task StartAsync(CancellationToken cancellationToken)
  {
    _timer = new Timer((object? state) => {
      using var scope = _serviceScopeFactory.CreateScope();
      var myService = scope.ServiceProvider.GetRequiredService<IMyService>();
      await myService.Execute(cancellationToken);            // <------ problem
    }), null, TimeSpan.Zero, TimeSpan.FromSeconds(5));

    return Task.CompletedTask;
  }

  public Task StopAsync(CancellationToken …
Run Code Online (Sandbox Code Playgroud)

c# async-await asp.net-core asp.net-core-hosted-services asp.net-core-5.0

19
推荐指数
1
解决办法
2万
查看次数

使用 ASP.NET Core 中的托管服务并行排队后台任务

我正在使用 ASP.NET Core 2.1 版中的托管服务功能对新的后台任务进行一些测试,更具体地说是使用排队后台任务,我想到了一个关于并行性的问题。

我目前严格遵循 Microsoft 提供的教程,并且在尝试模拟来自同一用户的多个请求以将任务排入队列时的工作负载时,我注意到所有工作项都是按顺序执行的,因此没有并行性。

我的问题是,这种行为是预期的吗?如果是这样,为了使请求执行并行,是否可以触发并忘记,而不是等待 workItem 完成?

我在没有运气的情况下搜索了几天有关此特定场景的信息,因此如果有人提供任何指南或示例,我会非常高兴。

编辑:教程中的代码很长,所以它的链接是https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.1#queued -背景任务

执行工作项的方法是这样的:

public class QueuedHostedService : IHostedService
{
    ...

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Queued Hosted Service is starting.");

        _backgroundTask = Task.Run(BackgroundProceessing);

        return Task.CompletedTask;
    }

    private async Task BackgroundProceessing()
    {
        while (!_shutdown.IsCancellationRequested)
        {
            var workItem = 
                await TaskQueue.DequeueAsync(_shutdown.Token);

            try
            {
                await workItem(_shutdown.Token);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, 
                    $"Error occurred executing {nameof(workItem)}.");
            }
        }
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

问题的重点是要知道是否有人可以分享有关如何使用此特定技术同时执行多个工作项的知识,因为服务器可以处理此工作负载。

我在执行工作项时尝试了即发即弃的方法,它按照我的预期工作,同时并行执行多个任务,我不确定这是否是一个好的做法,或者是否有处理这种情况的更好或正确的方法。

c# parallel-processing asp.net-core-2.1 asp.net-core-hosted-services

13
推荐指数
1
解决办法
7140
查看次数

'某些服务无法构建(验证服务描述符时出错'ServiceType:IHostedService

我正在使用 .NET 5,我想使用IHostedService类运行后台任务,如您所见:

public class PasargadJobs : IHostedService, IDisposable
{
    private Timer _timer = null!;
    readonly  ITerminalService _terminalService;
    readonly  IMessageService _messageService;
    readonly IMerchantService _merchantService;
    
    public PasargadJobs(
        IMerchantService merchantService,
        ITerminalService terminalService,
        IMessageService messageService)
    {
        _messageService = messageService;
        _terminalService = terminalService;
        _merchantService = merchantService;
    }
    
    //other parts of code are removed for short code
}
Run Code Online (Sandbox Code Playgroud)

所以我必须将它注入到服务集合中,如您所见:

services.AddHostedService<PasargadJobs>();
Run Code Online (Sandbox Code Playgroud)

但添加此后我收到此错误:

System.AggregateException:“无法构造某些服务(验证服务描述符时出错”ServiceType:Microsoft.Extensions.Hosting.IHostedService Lifetime:Singleton ImplementType:MIMS.Portal.ScheduleJobs.PasargadJobs”:无法使用作用域服务“Microsoft” .EntityFrameworkCore.DbContextOptions`1[MIMS.Portal.Infrustruct.Repositories.AppDbContext]'来自单例'Microsoft.Extensions.Hosting.IHostedService'。)'

这是我的startup.cs

services.AddExpressiveAnnotations();

//--- DB Context ---//
services.AddTransient<AppDbContext, AppDbContext>();
//--- Repositories ---//
services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));
services.AddTransient<IMerchantRepository, MerchantRepository>();
services.AddTransient<IBankAccountRepository, BankAccountRepository>();
services.AddTransient<IBankRepository, …
Run Code Online (Sandbox Code Playgroud)

dependency-injection background-task asp.net-core asp.net-core-hosted-services servicecollection

13
推荐指数
1
解决办法
5万
查看次数

如何为我的后台服务编写单元测试?

我正在使用 .NET Core 中的 HostBuilder(不是 WebHost !)。

我在我的应用程序中运行了一个托管服务,它覆盖了后台服务的 ExecuteAsync/StopAsync 方法,我想对其进行单元测试。

这是我的托管服务:

public class DeviceToCloudMessageHostedService : BackgroundService
{
    private readonly IDeviceToCloudMessageService _deviceToCloudMessageService;
    private readonly AppConfig _appConfig;

    public DeviceToCloudMessageHostedService(IDeviceToCloudMessageService deviceToCloudMessageService, IOptionsMonitor<AppConfig> appConfig)
    {
        _deviceToCloudMessageService = deviceToCloudMessageService;
        _appConfig = appConfig.CurrentValue;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            await _deviceToCloudMessageService.DoStuff(stoppingToken);
            await Task.Delay(_appConfig.Parameter1, stoppingToken);
        }
    }
    
    public override Task StopAsync(CancellationToken cancellationToken)
    {
        Log.Information("Task Cancelled");
        _deviceToCloudMessageService.EndStuff();
        return base.StopAsync(cancellationToken);
    }
Run Code Online (Sandbox Code Playgroud)

我已经找到了这篇文章:.NET Core 中托管服务的集成测试

但它是为 QueuedBackgroundService 解释的,我真的不知道我是否可以用同样的方式测试我的。

我只想知道我的代码是否被执行。我不想要任何具体的结果。你知道我如何测试它吗?

c# .net-core asp.net-core-hosted-services

12
推荐指数
1
解决办法
9340
查看次数

托管服务集成测试.Net-Core`

我有一个QueueTask托管服务(.Net-Core的新后台服务),我想测试.我的queuedHosted服务看起来像这样:

public QueuedHostedService(IServiceProvider serviceProvider, IBackgroundTaskQueue taskQueue, ILoggerFactory loggerFactory)
{
    TaskQueue = taskQueue;
    _logger = loggerFactory.CreateLogger<QueuedHostedService>();
    _serviceProvider = serviceProvider;
}

protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
    using (var scope = _serviceProvider.CreateScope())
    {
        while (false == stoppingToken.IsCancellationRequested)
        {
            var workItem = await TaskQueue.DequeueAsync(stoppingToken);
            try
            {
                await workItem(scope.ServiceProvider, stoppingToken);
            }
            catch (Exception ex)
            {
                this._logger.LogError(ex, $"Error occurred executing {nameof(workItem)}.");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它只是从队列中读取任务并在它们进入时执行它们.我已经验证了托管服务正在生产中.我为它写了一个测试:

[TestMethod]
public async Task Verify_Hosted_Service_Executes_Task()
{
    IServiceCollection services = new ServiceCollection();
    services.AddSingleton<ILoggerFactory, NullLoggerFactory>();
    services.AddHostedService<QueuedHostedService>();
    services.AddSingleton<IBackgroundTaskQueue, BackgroundTaskQueue>();
    var serviceProvider …
Run Code Online (Sandbox Code Playgroud)

c# mstest .net-core asp.net-core asp.net-core-hosted-services

11
推荐指数
1
解决办法
2639
查看次数

IHostedService 可以在 Azure Functions 应用程序中使用吗?

无论是否应该,我们可以IHostedService在 Azure Functions 应用程序中使用吗?

这是尝试将托管服务(特别是后台服务)注册为IHostedService

internal sealed class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddHostedService<ExampleBackgroundService>();
    }
}
Run Code Online (Sandbox Code Playgroud)

Functions App 然后抛出以下异常:

Microsoft.Azure.WebJobs.Script.InvalidHostServicesException: 'The following service registrations did not match the expected services:
  [Invalid] ServiceType: Microsoft.Extensions.Hosting.IHostedService, Lifetime: Singleton, ImplementationType: ExampleBackgroundService'
Run Code Online (Sandbox Code Playgroud)

c# azure background-service azure-functions asp.net-core-hosted-services

10
推荐指数
1
解决办法
1661
查看次数

在 ASP.NET Core 3.1 中,如何在未来的特定日期和时间安排带有托管服务的后台任务(Cron 作业)?

我正在开发一个基于 ASP.NET Core 3.1 的项目,我想向它添加一个特定的功能,以安排将来在帖子作者指定的日期和时间发布帖子(类似于 Wordpress 通过它的 cron 作业)。例如,如果我们从用户那里收到这个日期和时间:

2020-09-07 14:08:07

那么,如何通过使用托管服务仅运行一次并更改数据库中的标志并在此之后保存更改来为其安排后台任务?

我已经阅读了一些关于它的文章,但他们没有指定日期和时间,只是提到了每 5 秒重复一次的任务以及类似 cron 表达式的内容,但是,我需要知道的是如何安排后台任务特定日期和时间?

先感谢您。

c# scheduled-tasks asp.net-core asp.net-core-hosted-services

10
推荐指数
2
解决办法
1万
查看次数

.NET Core 中 tcp 服务器的 IHostedService

我正在尝试构建一个小型 tcp 服务器/守护进程,将 asp.net 核心作为 Web 前端与服务器进行交互。我发现 IHostedService/BackgroundService 似乎提供了一种将服​​务器和前端捆绑在一起的低成本替代方案。

代码目前看起来基本上是这样的(用于测试目的的回声服务器):

public class Netcat : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        TcpListener listener = new TcpListener(IPAddress.Any, 8899);
        listener.Start();
        while(!stoppingToken.IsCancellationRequested)
        {
            TcpClient client = await listener.AcceptTcpClientAsync();
            NetworkStream stream = client.GetStream();

            while (!stoppingToken.IsCancellationRequested)
            {
                byte[] data = new byte[1024];
                int read = await stream.ReadAsync(data, 0, 1024, stoppingToken);

                await stream.WriteAsync(data, 0, read, stoppingToken);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并在 Startup.cs 中初始化如下:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHostedService<Netcat>();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }
Run Code Online (Sandbox Code Playgroud)

对于现代 Asp.Net 核心应用程序和守护进程应该如何合作,是否有一个共同的模式? …

c# tcplistener .net-core asp.net-core asp.net-core-hosted-services

9
推荐指数
1
解决办法
6944
查看次数

.NET Core 在集成测试中停止 HostedService

我有 .NET Core Web API 项目,由于某些原因,我们在该项目中创建了一个后台服务,并在应用程序启动时开始运行后台服务。因此,我们创建了一个BackgroundWorkderService继承自BackgroundService (Microsoft.Extensions.Hosting)的 ,如下所示:

public class BackgroundWorkerService : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await DoWork(stoppingToken);
    }

    public override async Task StartAsync(CancellationToken cancellationToken)
    {
        await ExecuteAsync(cancellationToken);
    }

    public override Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}
Run Code Online (Sandbox Code Playgroud)

为了在应用程序启动时运行它,我将后台服务添加到 Program.cs 中的托管服务中,如下所示:

.ConfigureServices(services =>
                services.AddHostedService<BackgroundWorkerService>());
Run Code Online (Sandbox Code Playgroud)

现在,我们需要创建一个集成测试,并且我们希望在运行集成测试时停止后台服务。

有谁知道如何在集成测试中阻止它?我尝试从ConfigureTestServices 中删除该服务,但没有成功,集成测试开始时后台服务仍在运行。

c# integration-testing asp.net-core-hosted-services

9
推荐指数
2
解决办法
4490
查看次数