简体   繁体   中英

Mysterious Behavior of .NET Core Background Task

my first question is if this article by Microsoft is working for other programers: https://blogs.msdn.microsoft.com/cesardelatorre/2017/11/18/implementing-background-tasks-in-microservices-with-ihostedservice-and-the-backgroundservice-class-net-core-2-x/

There is explained how i can use background-services. I have a program which has a WEB API where the data input is inserted to a database. My background job should show every minute if there is new data in the database and should handle some request to other webservices.

My problem is, that sometimes it triggers twice or the job isn't running. I print to the console every time the background service is doing it's job the timestamp. And after a while there is nothing printed out anymore.

Here is my sample-code. Is there something wrong with my code or configuration?

First Code-Sample is the code of the Startup-Class in the ConfigureService Method:

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

Here is the implementation of the class which holds the logic of my background service:

 /// <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();
    }
}

I fixed the problem by using the provided solution with an endless loop. From now, there is no mysterious behavior about timeouts and cancelled tasks.

The solution looks like the following:

     /// <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();
    }
}

Hopefully it helps you too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM