web-dev-qa-db-ja.com

ASP.NET Core IHostedService手動開始/停止/一時停止(?)

要求に応じて停止および開始できるASPNET Coreで、定期的な(時間指定された)IHostedServiceインスタンスを実装したいと思います。私の理解では、IHostedService(s)はアプリケーションの起動時にフレームワークによって開始されます。

ただし、おそらくUIを介してオン/オフ切り替えを使用して、「手動」でサービスを開始/停止できるようにしたいと思います。理想的には、「オフ」状態は現在実行中のサービスを破棄し、「オン」状態は新しいインスタンスを作成します。

ここでMSドキュメントを読みました: https://docs.Microsoft.com/en-us/aspnet/core/fundamentals/Host/hosted-services?view=aspnetcore-2.1

私の最初の考えは、実行中のサービスのインスタンスを取得してから、パブリックStopAsync(CancellationToken token)メソッドを呼び出すことでした。しかし、どのトークンを渡すべきかについては少し行き詰まっており、StartAsync(CancellationToken cancellationToken)メソッドについても同じことが言えます。

これがどのように行われるべきか、またはそれが賢明であるかどうかについてのアイデアはありますか?私のアプローチは、ASPNET Coreのホストされたサービスの意図された設計に何らかの形で反していますか?

EDIT 7.27.2018

そのため、ホストのStartAsync/StopAsyncメソッドが実際にアプリケーションの存続期間と一致することを意図していることをさらに調査した後(別名ドキュメントを読む:D)に表示されます。登録されたIHostedServicesは、他のクラスに注入するためにDIコンテナーに追加されていないようです。

したがって、最初のアイデアがうまくいくとは思いません。今のところ、構成の依存関係(IOptions<T>)実行時に更新できます。ホストされたサービスは処理中に、構成をチェックして続行する必要があるかどうかを確認します。そうでない場合は、ホストされたサービスを停止または破棄する代わりに待機します。

他のアイデアを聞いていない限り、おそらくすぐにこれを回答としてマークします。

15
K. Akins

StopAsync(CancellationToken token)の場合、new System.Threading.CancellationToken()を渡すことができます。 public CancellationToken(bool canceled)の定義では、canceledはトークンの状態を示します。シナリオでは、サービスを停止するため、canceledを指定する必要はありません。

次のステップごとに実行できます。

  1. IHostedServiceを作成

       public class RecureHostedService : IHostedService, IDisposable
     {
    private readonly ILogger _log;
    private Timer _timer;
    public RecureHostedService(ILogger<RecureHostedService> log)
    {
        _log = log;
    }
    
    public void Dispose()
    {
        _timer.Dispose();
    }
    
    public Task StartAsync(CancellationToken cancellationToken)
    {
        _log.LogInformation("RecureHostedService is Starting");
        _timer = new Timer(DoWork,null,TimeSpan.Zero, TimeSpan.FromSeconds(5));
        return Task.CompletedTask;
    }
    
    public Task StopAsync(CancellationToken cancellationToken)
    {
        _log.LogInformation("RecureHostedService is Stopping");
        _timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }
    private void DoWork(object state)
    {
        _log.LogInformation("Timed Background Service is working.");
    }
    }
    
  2. 登録IHostedService

        services.AddSingleton<IHostedService, RecureHostedService>();
    
  3. サービスの開始と停止

     public class HomeController : Controller {
     private readonly RecureHostedService _recureHostedService;
     public HomeController(IHostedService hostedService)
     {
         _recureHostedService = hostedService as RecureHostedService;
     }
     public IActionResult About()
     {
         ViewData["Message"] = "Your application description page.";
         _recureHostedService.StopAsync(new System.Threading.CancellationToken());
         return View();
     }
    
     public IActionResult Contact()
     {
         ViewData["Message"] = "Your contact page.";
         _recureHostedService.StartAsync(new System.Threading.CancellationToken());
         return View();
     } }
    
10
Tao Zhou