Таинственное поведение основной фоновой задачи .NET - PullRequest
0 голосов
/ 03 сентября 2018

Мой первый вопрос: работает ли эта статья от Microsoft для других программистов: https://blogs.msdn.microsoft.com/cesardelatorre/2017/11/18/implementing-background-tasks-in-microservices-with-ihostedservice-and-the-backgroundservice-class-net-core-2-x/

Там объясняется, как я могу использовать background-services. У меня есть программа, которая имеет веб-API, где ввод данных вводится в базу данных. Моя фоновая работа должна показывать каждую минуту, если в базе данных есть новые данные, и должна обрабатывать некоторые запросы к другим веб-сервисам.

Моя проблема в том, что иногда он срабатывает дважды или задание не выполняется. Я печатаю на консоль каждый раз, когда фоновая служба выполняет свою работу, отметку времени. И через некоторое время больше ничего не распечатывается.

Вот мой пример кода. Что-то не так с моим кодом или конфигурацией?

Первый пример кода - это код класса запуска в методе ConfigureService:

//Adding Background Task Class to Hosted Services in Startup-Class and Method ConfigureServices
services.AddHostedService<JsonDataCreator>();

Вот реализация класса, который содержит логику моего фонового сервиса:

 /// <summary>
/// Background Service which creates the JSON Files for the machine
/// </summary>
public class JsonDataCreator : IHostedService, IDisposable
{
    private readonly ILogger _logger;
    private Timer _timer;

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="logger">Logger functionallity</param>
    public JsonDataCreator(ILogger<JsonDataCreator> logger)
    {
        _logger = logger;
    }


    /// <summary>
    /// Task which is executed Asynchronous
    /// </summary>
    /// <param name="cancellationToken">Cancellation token for stopping the Task</param>
    /// <returns>Task Completed</returns>
    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is starting");
        Console.WriteLine("Timed Background Service is starting");
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
        return Task.CompletedTask;
    }

    /// <summary>
    /// Logical Request to Webservice + Database and creation of JSON Files
    /// </summary>
    /// <param name="state"></param>
    private void DoWork(object state)
    {
        try
        {
            Console.WriteLine("Begin new Round of Background-Work" +                                     DateTime.Now.ToShortTimeString());
            //THERE IS SOME LOGIC INSIDE WHICH CALLS SOME WEBSERVICE
        }catch(Exception ex)
        {

            Console.WriteLine(ex.Message);
        }                 
    }

    /// <summary>
    /// Stops the Task
    /// </summary>
    /// <param name="cancellationToken"></param>
    /// <returns>Task Completed</returns>
    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is stopping");
        Console.WriteLine("Timed Background Service is stopping");
        _timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }

    /// <summary>
    /// Disposes the Task
    /// </summary>
    public void Dispose()
    {
        _timer?.Dispose();
    }
}

1 Ответ

0 голосов
/ 24 января 2019

Я исправил проблему, используя предоставленное решение с бесконечным циклом. Отныне нет таинственного поведения в отношении таймаутов и отмененных задач.

Решение выглядит следующим образом:

     /// <summary>
/// Background Service which creates the JSON Files for the machine
/// </summary>
public class JsonDataCreator : IHostedService, IDisposable
{
    private readonly ILogger _logger;
    private Timer _timer;

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="logger">Logger functionallity</param>
    public JsonDataCreator(ILogger<JsonDataCreator> logger)
    {
        _logger = logger;
    }


    /// <summary>
    /// Task which is executed Asynchronous
    /// </summary>
    /// <param name="cancellationToken">Cancellation token for stopping the Task</param>
    /// <returns>Task Completed</returns>
    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is starting");
        while(true){
            //Do the business logic
            //Wait the time you want
        }
        return Task.CompletedTask;
    }



    /// <summary>
    /// Stops the Task
    /// </summary>
    /// <param name="cancellationToken"></param>
    /// <returns>Task Completed</returns>
    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is stopping");
        Console.WriteLine("Timed Background Service is stopping");
        _timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }

    /// <summary>
    /// Disposes the Task
    /// </summary>
    public void Dispose()
    {
        _timer?.Dispose();
    }
}

Надеюсь, вам это тоже поможет.

...