IHostedService的多个实现

Jam*_*mes 5 c# asp.net-core asp.net-core-2.0

我正在尝试使用IHostedService创建后台服务.如果我只有一个后台服务,一切正常.当我尝试创建多个实现时,IHostedService只有第一个实际运行的实现.

services.AddSingleton<IHostedService, HostedServiceOne>();
services.AddSingleton<IHostedService, HostedServiceTwo>();
Run Code Online (Sandbox Code Playgroud)

在上面的例子StartAsyncHostedServiceOne被调用,但StartAsyncHostedServiceTwo不会被调用.如果我换登记的两种实现方式的顺序IHostedService(把IHostedServiceTwoIHostedServiceOne),然后StartAsyncHostedServiceTwo被调用而从来不是HostedServiceOne.

编辑:

我被引导到以下内容:

如何在Asp.Net Core中注册同一接口的多个实现?

然而,这不适合IHostedService.要使用建议的方法,我将不得不打电话,serviceProvider.GetServices<IService>();但似乎IHostedService.StartAsync似乎在内部调用.我甚至不确定我会在哪里触发它IHostedService.StartAsync.

小智 7

我有同样的问题。必须在每个服务中返回Task.CompletedTask;

public class MyHostedService: IHostedService
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        Task.Run(() => SomeInfinityProcess(cancellationToken));
        return Task.CompletedTask;
    }

    public void SomeInfinityProcess(CancellationToken cancellationToken)
    {
        for (; ; )
        {
            Thread.Sleep(1000);
            if (cancellationToken.IsCancellationRequested)
                break;
        }
    }

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

Startup.cs是相同的:

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


itm*_*nus 6

注册HostedService如下:

// services.AddSingleton<IHostedService, HostedServiceOne>();
// services.AddSingleton<IHostedService, HostedServiceTwo>();

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

它将按预期工作.


Jav*_*llo 1

这似乎可以通过装饰来解决IHostedService,尽管.Net Core的默认IoC容器不支持注册装饰器,但有一个简单的解决方法。

您可以像这样创建一个装饰器IHostedService

public abstract class MyHostedServiceDecorator : IHostedService
{
    private readonly MyHostedServiceDecorator _next;

    protected MyHostedServiceDecorator(MyHostedServiceDecorator next)
    {
        _next = next;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        await StartAsyncInternal(cancellationToken);

        if (_next != null)
        {
            await _next.StartAsync(cancellationToken);
        }
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        await StopAsyncInternal(cancellationToken);

        if (_next != null)
        {
            await _next.StopAsync(cancellationToken);
        }
    }

    protected abstract Task StartAsyncInternal(CancellationToken token);

    protected abstract Task StopAsyncInternal(CancellationToken token);
}
Run Code Online (Sandbox Code Playgroud)

创建您需要的尽可能多的装饰器,例如:

public class HostedServiceOneDecorator : MyHostedServiceDecorator
{
    public HostedServiceOneDecorator(MyHostedServiceDecorator next) : base(next)
    {
    }

    protected override async Task StartAsyncInternal(CancellationToken token)
    {
        Console.Write("This is my decorated start async!");
    }

    protected override async Task StopAsyncInternal(CancellationToken token)
    {
        Console.Write("This is my decorated stop async!");
    }
}
Run Code Online (Sandbox Code Playgroud)

在您注册的托管服务中,像这样调用装饰器:

public class MyHostedService : IHostedService
{
    private readonly MyHostedServiceDecorator
        _decorator;

    public MyHostedService(MyHostedServiceDecorator decorator)
    {
        _decorator = decorator;
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        // base StartAsync logic ...
        await _decorator.StartAsync(cancellationToken);
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        // base StopAsync logic ...
        await _decorator.StopAsync(cancellationToken);
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,通过在前一个构造函数中传递下一个装饰器来注册服务及其装饰器。

services.AddSingleton<IHostedService, MyHostedService>();

services.AddSingleton<MyHostedServiceDecorator>(
    new HostedServiceOneDecorator(new HostedServiceTwoDecorator(/*etc*/)));
Run Code Online (Sandbox Code Playgroud)

所有的装饰器都会以链式的方式被调用,直到没有下一个!