Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.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# 同时运行长任务IHosted服务,可以手动打开和关闭_C#_Asp.net Core_Backgroundworker_Asp.net Core Hosted Services - Fatal编程技术网

C# 同时运行长任务IHosted服务,可以手动打开和关闭

C# 同时运行长任务IHosted服务,可以手动打开和关闭,c#,asp.net-core,backgroundworker,asp.net-core-hosted-services,C#,Asp.net Core,Backgroundworker,Asp.net Core Hosted Services,您好,我在使用IHostedService为我的后台服务运行一个长任务时遇到了问题。起初,它确实工作正常,但从长远来看,后台服务突然停止,出现以下线程退出代码: The thread 10824 has exited with code 0 (0x0). The thread 12340 has exited with code 0 (0x0). The thread 9324 has exited with code 0 (0x0). The thread 11168 has exited w

您好,我在使用IHostedService为我的后台服务运行一个长任务时遇到了问题。起初,它确实工作正常,但从长远来看,后台服务突然停止,出现以下线程退出代码:

The thread 10824 has exited with code 0 (0x0).
The thread 12340 has exited with code 0 (0x0).
The thread 9324 has exited with code 0 (0x0).
The thread 11168 has exited with code 0 (0x0).
The thread 11616 has exited with code 0 (0x0).
The thread 9792 has exited with code 0 (0x0).
我将我的后台服务注册为

//Register Background 
serviceCollection.AddSingleton<CoinPairBackgroundService>
serviceCollection.AddSingleton<SaveFakePersonBackgroundService>();
serviceCollection.AddSingleton<LeaderboardMinutesBackgroundService>();
serviceCollection.AddSingleton<LeaderboardHoursBackgroundService>();

serviceCollection.AddSingleton<IHostedService, CoinPairBackgroundService>();
serviceCollection.AddSingleton<IHostedService, SaveFakePersonBackgroundService>();
serviceCollection.AddSingleton<IHostedService, LeaderboardMinutesBackgroundService>();
serviceCollection.AddSingleton<IHostedService, LeaderboardHoursBackgroundService>();

我对注册我的后台服务是否有问题感到困惑,因为我看到我的后台服务启动了,但从长远来看,它突然停止了。我已经摆脱了那些线程。我的后台服务中的Sleep()希望你能提前帮到我,谢谢。

而不是以如此奇怪的方式管理托管服务的生命周期,您可以为
appsettings.json
内的服务设置配置,将其配置为
reloadOnChange:true
,并使用
IOptionsMonitor
appsettings.json
访问当前值。并将该设置用作在托管服务的
StartAsync
方法中取消已启动的任务。您需要收听
IOptionsMonitor
OnChange
事件以重新启动服务

appsettings.json

 "HostedService": {
    "RunService1": true
  }
注册该选项,以便:

public class HostedServiceConfig
{
     public bool RunService1 { get; set; }
}

services.Configure<HostedServiceConfig>(Configuration.GetSection("HostedService"));
下面是
StartAsync
的示例:

  public class HostedService1 : IHostedService
  {
        private readonly IOptionsMonitor<HostedServiceConfig> _options;
        private CancellationToken _cancellationToken;

        public HostedService1(IOptionsMonitor<HostedServiceConfig> options)
        {
            _options = options;

             // Or listen to changes and re-run all services from one place inside `Configure` method of `Startup`
            _options.OnChange(async o =>
            {
                if (o.RunService1)
                {
                    await StartAsync(_cancellationToken);
                }
            });
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            if(_cancellationToken == null) 
            {
                 _cancellationToken = cancellationToken;
            }

            Task.Run(async () =>
            {
                while (!_cancellationToken .IsCancellationRequested || !_options.CurrentValue.RunService1)
                {
                     ....
                }
            });

            return Task.CompletedTask;
        }

        ...
   }
公共类HostedService 1:IHostedService
{
专用只读IOptionsMonitor选项;
私有取消令牌\u取消令牌;
公共托管服务1(IOptionsMonitor选项)
{
_选项=选项;
//或者在“启动”的“配置”方法中,侦听更改并从一个位置重新运行所有服务`
_options.OnChange(异步o=>
{
如果(o.RunService1)
{
等待StartSync(_cancellationToken);
}
});
}
公共任务StartSync(CancellationToken CancellationToken)
{
if(_cancellationToken==null)
{
_cancellationToken=cancellationToken;
}
Task.Run(异步()=>
{
while(!\u cancellationToken.IsCancellationRequested | |!\u options.CurrentValue.RunService1)
{
....
}
});
返回Task.CompletedTask;
}
...
}

如果
appSettings.json
中有任何更改,您的
\u options.CurrentValue.RunService1
将自动重新加载。

为什么要注册两次?为什么不使用
AddHostedService
?@FarhadJabiyev,这是因为我无法在不首先注册实现IHostedService的具体类的情况下获得IHostedService,正如您所看到的,我使用的是StartAsync()和StopAsync()手动打开和关闭我的BackgroundService的iHosteService功能在配置服务时决定运行哪些服务是不好的。相反,只需在
appsettings.json
中创建其他配置,并检查
StartAsync
中的值即可。如果已关闭,则只返回已完成的结果。@FarhadJabiyev这意味着我的appsettings.json中将有一个变量更改了其用于打开和关闭后台服务的值?如果我有多个后台服务,这意味着我的appsettings.json中的变量太多了怎么办?这是appsettings存在的原因,但我的问题是,当后台服务在StartAsync()中中断循环时,如何重新启动后台服务?有没有办法让这个HostedService 1再次运行?@JamesTubiano哦,明白了,你需要自动重新启动它?或者从
appsettings
手动启动是否正常?我想手动重新启动它是否有任何方法可以使用appsettings手动启动和停止HostedService 1?
public class HostedServiceConfig
{
     public bool RunService1 { get; set; }
}

services.Configure<HostedServiceConfig>(Configuration.GetSection("HostedService"));
 services.AddHostedService<HostedService1>();
  public class HostedService1 : IHostedService
  {
        private readonly IOptionsMonitor<HostedServiceConfig> _options;
        private CancellationToken _cancellationToken;

        public HostedService1(IOptionsMonitor<HostedServiceConfig> options)
        {
            _options = options;

             // Or listen to changes and re-run all services from one place inside `Configure` method of `Startup`
            _options.OnChange(async o =>
            {
                if (o.RunService1)
                {
                    await StartAsync(_cancellationToken);
                }
            });
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            if(_cancellationToken == null) 
            {
                 _cancellationToken = cancellationToken;
            }

            Task.Run(async () =>
            {
                while (!_cancellationToken .IsCancellationRequested || !_options.CurrentValue.RunService1)
                {
                     ....
                }
            });

            return Task.CompletedTask;
        }

        ...
   }