亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在沒有 http 請求的情況下在 MVC Core 應用程序中啟動 HostedService

如何在沒有 http 請求的情況下在 MVC Core 應用程序中啟動 HostedService

C#
繁花不似錦 2022-07-23 17:32:12
在我的 MVC .NET core 2.2 應用程序中有 HostedService 做后臺工作。在 Startap 類的 ConfigureServices 方法中注冊services.AddHostedService<Engines.KontolerTimer>();由于這是獨立于用戶請求的后臺服務,我想在應用程序啟動時立即啟動我的后臺服務?,F在是我的 HostedService 在第一個用戶請求之后盯著的情況。MVC Core 應用程序啟動時啟動 HostedService 的正確方法是什么我的服務看起來像這樣https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.2internal class TimedHostedService : IHostedService, IDisposable{    private readonly ILogger _logger;    private Timer _timer;    public TimedHostedService(ILogger<TimedHostedService> logger)    {        _logger = logger;    }    public Task StartAsync(CancellationToken cancellationToken)    {        _logger.LogInformation("Timed Background Service is starting.");        _timer = new Timer(DoWork, null, TimeSpan.Zero,             TimeSpan.FromSeconds(5));        return Task.CompletedTask;    }    private void DoWork(object state)    {        _logger.LogInformation("Timed Background Service is working.");    }    public Task StopAsync(CancellationToken cancellationToken)    {        _logger.LogInformation("Timed Background Service is stopping.");        _timer?.Change(Timeout.Infinite, 0);        return Task.CompletedTask;    }    public void Dispose()    {        _timer?.Dispose();    }}看起來我根本無法盯著應用程序。我的 porgram cs 看起來像public class Program    {        public static void Main(string[] args)        {           CreateWebHostBuilder(args).Build().Run();        }        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>            WebHost.CreateDefaultBuilder(args)            .UseSerilog((ctx, config) => { config.ReadFrom.Configuration(ctx.Configuration); })            .UseStartup<Startup>();    }而且在第一次用戶請求之前我沒有遇到任何斷點。我錯過了什么嗎,這是 VS2017 創建的默認 .Net Core 應用程序
查看完整描述

5 回答

?
幕布斯6054654

TA貢獻1876條經驗 獲得超7個贊

當您使用 Visual Studio 運行它時,您可能會使用 IIS Express,它不會在發出第一個請求之前運行您的 ASP.NET Core 項目(這實際上就是 IIS 默認的工作方式)。這適用于使用 ASP.NET Core 2.2 中新增的 InProcess 托管模型,我希望您必須使用它才能看到此問題。有關更多信息,請參閱此GitHub 問題

您可以通過從用于托管 ASP.NET Core 應用程序的 .csproj 文件中刪除 AspNetCoreHostingModel XML 元素來證明這一理論(這會將其切換回 OutOfProcess 模式)??雌饋鞻S2017的項目屬性對話框中的“調試”下有一個“托管模型”選項,如果您不想直接編輯.csproj,可以將其更改為“進程外”。

例如,如果您希望托管模型僅用于生產站點的進程外,則可以使用 Web.config 轉換。如果您希望它在開發和生產過程中都處于進程外,只需更改我在上面調用的屬性就足夠了,因為它會自動轉換為 Web.config 屬性。如果您希望使用進程內模型,在 IIS 應用程序中啟用預加載是一個不錯的選擇(在此處描述)。


查看完整回答
反對 回復 2022-07-23
?
有只小跳蛙

TA貢獻1824條經驗 獲得超8個贊

后臺服務在您的應用程序啟動時啟動,然后由您決定與之同步。


您可以使用命名空間(程序集)中的BackgroundService類來實現后臺服務:Microsoft.Extensions.HostingMicrosoft.Extensions.Hosting.Abstractions


首先聲明你的服務的接口(在這種情況下它是空的,不是很好,但很干凈):


public interface IMyService : IHostedService

{

}

然后,聲明您的服務。以下代碼段聲明了一個服務,該服務在啟動時持續 5 秒,然后每 2 分半鐘執行一次任務:


internal sealed class MyService : BackgroundService, IMyService

{

    private const int InitialDelay = 5 * 1000;  //5 seconds;

    private const int Delay = (5 * 60 * 1000) / 2; // 2.5 minutes


    private readonly ILogger<MyService> m_Logger;


    public MyService(ILogger<MyService> logger, IServiceProvider serviceProvider)

    {

        if (logger == null)

            throw new ArgumentNullException(nameof(logger));

        if (serviceProvider == null)

            throw new ArgumentNullException(nameof(serviceProvider));


        this.m_Logger = logger;

        this.m_ServiceProvider = serviceProvider;

    }


    protected override async Task ExecuteAsync(CancellationToken stoppingToken)

    {

        try

        {

            m_Logger.LogDebug($"MyService is starting.");


            stoppingToken.Register(() => m_Logger.LogDebug($"MyService background task is stopping because cancelled."));


            if (!stoppingToken.IsCancellationRequested)

            {

                m_Logger.LogDebug($"MyService is waiting to be scheduled.");

                await Task.Delay(InitialDelay, stoppingToken);

            }


            m_Logger.LogDebug($"MyService is working.");


            while (!stoppingToken.IsCancellationRequested)

            {

                await DoSomethingAsync();


                await Task.Delay(Delay);

            }


            m_Logger.LogDebug($"MyService background task is stopping.");

        }

        catch (Exception ex)

        {

            m_Logger.LogDebug("MyService encountered a fatal error while w task is stopping: {Exception}.", ex.ToString());

        }

    }


    private async Task DoSomethingAsync()

    {

         // do something here

         await Task.Delay(1000);

    }

}

如您所見,讓后臺服務“活動”取決于您。最后,您必須在您的方法Startup.cs結束時將其注冊ConfigureServices:


services.AddSingleton<Microsoft.Extensions.Hosting.IHostedService, MyService>();

這足以啟動服務。請記住,如果托管在 IIS 中,您的應用程序實際上可能會在以后啟動:每次回收程序集時,您的應用程序都會(重新)啟動。相反,使用 Kestrel 提供了一個不會被回收的單實例應用程序。


對于那些使用 .Net Core 2.1 或更低版本的人,Background 類不可用,但您可以從 github 獲取定義(我發布了我過去使用的內容,因為 github 存儲庫可以移動):


//borrowed from .NET Core 2.1 (we are currently targeting 2.0.3)

// Copyright (c) .NET Foundation. Licensed under the Apache License, Version 2.0.

/// <summary>

/// Base class for implementing a long running <see cref="IHostedService"/>.

/// </summary>

public abstract class BackgroundService : IHostedService, IDisposable

{

    private Task _executingTask;


    private readonly CancellationTokenSource _stoppingCts =

                                                   new CancellationTokenSource();


    protected abstract Task ExecuteAsync(CancellationToken cancellationToken);


    public virtual Task StartAsync(CancellationToken cancellationToken)

    {

        // Store the task we're executing

        _executingTask = ExecuteAsync(_stoppingCts.Token);


        // If the task is completed then return it,

        // this will bubble cancellation and failure to the caller

        if (_executingTask.IsCompleted)

        {

            return _executingTask;

        }


        // Otherwise it's running

        return Task.CompletedTask;

    }


    public virtual async Task StopAsync(CancellationToken cancellationToken)

    {

        // Stop called without start

        if (_executingTask == null)

        {

            return;

        }


        try

        {

            // Signal cancellation to the executing method

            _stoppingCts.Cancel();

        }

        finally

        {

            // Wait until the task completes or the stop token triggers

            await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite,

                                                          cancellationToken));

        }

    }


    public virtual void Dispose()

    {

        _stoppingCts.Cancel();

    }

}


查看完整回答
反對 回復 2022-07-23
?
慕勒3428872

TA貢獻1848條經驗 獲得超6個贊

如果您想要一個服務來執行后臺任務(類似于舊的 Windows 服務),我建議您使用:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host? view=aspnetcore-2.2而不是 WebHost。

WebHost 添加了很多您可能不需要的東西,因為這似乎是一個簡單的后臺工作(假設閱讀您的代碼)。


查看完整回答
反對 回復 2022-07-23
?
墨色風雨

TA貢獻1853條經驗 獲得超6個贊

對我來說......后臺任務直到第一頁請求才開始。

但后來我注意到在我的發布/編輯中,我沒有設置目標網址。(而且我沒有主頁索引頁面)......

一旦我添加了一個有效的目標網址......該頁面將在發布后彈出并成為我的“第一個”頁面請求,后臺任務將開始。


查看完整回答
反對 回復 2022-07-23
?
達令說

TA貢獻1821條經驗 獲得超6個贊

托管服務確實在主機啟動時啟動。使用 WebHost,托管服務將在應用程序啟動后立即啟動。這意味著如果實施得當,您的托管服務將無需請求即可運行。

當我在一個新的 ASP.NET Core 應用程序上嘗試你的示例托管服務時,它工作得很好,所以如果它不適合你,那么顯然你的實際實現KontolerTimer是不正確的。


查看完整回答
反對 回復 2022-07-23
  • 5 回答
  • 0 關注
  • 169 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號