Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有没有办法在Asp.NETCore3.1中手动启动BackgroundService_C#_Asp.net Core_Asp.net Core 3.1_Ihostedservice - Fatal编程技术网

C# 有没有办法在Asp.NETCore3.1中手动启动BackgroundService

C# 有没有办法在Asp.NETCore3.1中手动启动BackgroundService,c#,asp.net-core,asp.net-core-3.1,ihostedservice,C#,Asp.net Core,Asp.net Core 3.1,Ihostedservice,我知道在Asp.Net 3.0(或3.1)之前,要手动启动BackgroundService,我们可以从IHostedService派生它,并将DI注册更改为: services.AddSingleton<IHostedService, CustomHostedService>(); 手动触发后台服务启动的最佳方式是什么 基本上,这是我的设置: 后台服务 public MyBackgroundService(Func<string, IConsumer> consume

我知道在Asp.Net 3.0(或3.1)之前,要手动启动BackgroundService,我们可以从
IHostedService
派生它,并将DI注册更改为:

services.AddSingleton<IHostedService, CustomHostedService>();
手动触发后台服务启动的最佳方式是什么

基本上,这是我的设置:

后台服务

public MyBackgroundService(Func<string, IConsumer> consumerFactory)
{
    _consumerFactory = consumerFactory ?? throw new ArgumentNullException(nameof(consumerFactory));
}
public MyBackgroundService(Func consumerFactory)
{
_consumerFactory=consumerFactory??抛出新的ArgumentNullException(nameof(consumerFactory));
}
消费者工厂注册

services.AddSingleton<Func<string, IConsumer>>(provider => providerName => provider.ConfigureConsumer(environment, providerName));

private static IConsumer ConfigureConsumer(this IServiceProvider provider, IHostEnvironment environment, string provideName)
{
    if (string.IsNullOrEmpty(provideName))
        throw new ArgumentNullException(nameof(provideName));

    var options = provider.GetRequiredService<IOptions<ConsumerConfig>>();
    if (options?.Value == null)
        throw new ArgumentNullException(nameof(options));

    return environment.IsDevelopment() 
        ? new Consumer(options, provider.GetTopics()) 
        : new Consumer((IOptions<ConsumerConfig>)options.SetSecurityOptions(provider), provider.GetTopics());
}

private static IOptions<Config> SetSecurityOptions(this IOptions<Config> config, IServiceProvider provider)
{
    var certService = provider.GetRequiredService<IVaultCertificateService>();
    ...
    return config;
}
services.AddSingleton(provider=>providerName=>provider.ConfigureConsumer(environment,providerName));
专用静态IConsumer配置使用者(此IServiceProvider提供程序、IHostEnvironment环境、字符串名称)
{
if(string.IsNullOrEmpty(provideName))
抛出新ArgumentNullException(nameof(provideName));
var options=provider.GetRequiredService();
如果(选项?.Value==null)
抛出新ArgumentNullException(nameof(options));
return-environment.IsDevelopment()
?新使用者(选项,provider.GetTopics())
:新使用者((IOOptions)选项。设置安全选项(提供程序),提供程序。GetTopics());
}
专用静态IOptions设置安全选项(此IOptions配置,IServiceProvider提供程序)
{
var certService=provider.GetRequiredService();
...
返回配置;
}
本质上,这个certService属性只在请求进入并执行中间件时设置。由于后台服务中的
ExecuteAsync()
尝试从工厂获取consumer实例时,不管执行情况如何,我都没有正确配置IConsumer
谢谢

注入式托管服务从应用程序开始,然后停止。框架不提供手动控制。这应该有潜在的原因。当然,您可以使用线程实现自己的解决方案,但如果您希望继续使用Microsoft的内置解决方案,您可以使用。您将使用空任务队列启动后台服务。服务将侦听要添加到队列的第一个任务。您可以随时添加任务,然后它将在后台运行。

当主机将手动启动任务作为启动过程的一部分时,为什么您需要手动启动它?只有在执行certian中间件时,才能使用构建bckground服务的一个依赖项所需的一些配置信息(当收到请求时)。并且该依赖项需要注册为singleton,因此我想知道,一旦第一个请求传入,我是否可以手动启动HostedService?我欢迎任何建议,如果有更好的方法来处理此场景?我可以考虑的另一种方法是创建StartupFilter并在那里加载配置,然后注册注册StartupFilter后的HosteServices?只需再次检查。在我们的3.1实现中不会自动启动。我们明确需要
\uuU9=app.ApplicationServices.GetService();
中的
Startup.Configure()
自动启动后台服务。如果不存在,则服务不会被解析,因此不会被实例化。我们需要向注入此服务的其中一个控制器发送请求,正如您所描述的那样。@MarkusDeibel我们没有。接口没有更改。OP使用
AddSingleton做了什么不需要,实际上是一个坏主意,因为它干扰了后台服务生命周期管理-即使在服务停止后,它仍处于活动状态。更糟糕的是,它引入了整个作用域服务问题-单例服务将从何处获得它所需的任何作用域服务?是的,我知道HostedService位于何处在管道中。我遇到的问题是关于在服务的构造函数中构造依赖关系。当certian中间件执行时,构造该依赖关系所需的数据可用,并且由于ExecuteAsync与应用程序启动(使用该依赖关系)并行启动,因此我没有正确构造的依赖关系当时是。好吧。你可以尝试将服务惰性地注入DI。这样你就可以控制DI何时将服务加载到容器并运行服务的构造函数。如果是开源项目,我在看到你当前的应用程序结构后会更清楚,但理论上,添加惰性服务可以作为解决方案应用:服务.AddTransient();
services.AddSingleton<Func<string, IConsumer>>(provider => providerName => provider.ConfigureConsumer(environment, providerName));

private static IConsumer ConfigureConsumer(this IServiceProvider provider, IHostEnvironment environment, string provideName)
{
    if (string.IsNullOrEmpty(provideName))
        throw new ArgumentNullException(nameof(provideName));

    var options = provider.GetRequiredService<IOptions<ConsumerConfig>>();
    if (options?.Value == null)
        throw new ArgumentNullException(nameof(options));

    return environment.IsDevelopment() 
        ? new Consumer(options, provider.GetTopics()) 
        : new Consumer((IOptions<ConsumerConfig>)options.SetSecurityOptions(provider), provider.GetTopics());
}

private static IOptions<Config> SetSecurityOptions(this IOptions<Config> config, IServiceProvider provider)
{
    var certService = provider.GetRequiredService<IVaultCertificateService>();
    ...
    return config;
}