Call function at each time interval efficiently

Asked

Viewed 5,604 times

3

I have a question, I am making a game server and I need a specific function to be rotated every 10 seconds.

I know there’s a Thread.Sleep() (in combination with a while(true)), but it doesn’t seem like a good option

I’ve heard of Timers (I tried to use, but for some reason he only calls the first time and then to) and Windows Services.

How do I call a function at each time interval efficiently?

  • Is using some database?

  • Yes, I use SQL Server

  • See if that answer helps you. With the Hangfire you can make a function run in the background with the time you want.

  • @Randrade in his case will not be possible to use Hangfire, unfortunately the Recurring jobs gets a CRON scheduleto set the time, and the shortest range that can be set using a CRON is 1 minute.

  • @Tobymosque It depends on the shape he wants to use. You can set the 10 seconds as the time he searches for the Jobs in the bank, and not by CRON. If that’s all there is to it.

  • @Tobymosque It is worth remembering that their github already have some issues for this issue.

  • You should be careful with the Timer as it will run every 10 seconds regardless of whether the last process is over or not.

Show 2 more comments

4 answers

6


There is the possibility to do also with Reactive Extensions, asynchronous based on events.

Add the package via nuget

Install-Package System.Reactive

var observable = Observable
    .Interval(TimeSpan.FromSeconds(10))
        //.Do((x) => { }) // log events 
    ;

//primeiro subscriber
observable.Subscribe((x) =>
{
    Console.WriteLine($"multiplica {x} x 2 = {x * 2}");
});

//segundo subscriber
observable.Subscribe((x) =>
{
    Console.WriteLine($"potência {x}^2 = {Math.Pow(x, 2)}");
});

This way several actions can respond (subscribers) to this event generator, in my opinion leaves the code better structured.

  • 1

    It worked perfectly =) I just wanted to say what package name changed from Rx-Main to System.Reactive Thanks =)

  • 1

    The package Rx-Main was the previous version 2.0, actually version 3.0 changed the package id.

6

Using timers

Generates an event after a defined interval in order to generate events recurring.

Use the Timer as follows:

public class Servidor
{
public static System.Timers.Timer _timer;
public static void Main()
{

    _timer = new System.Timers.Timer();
    _timer.AutoReset = false;
    _timer.Interval = 1000; // Intervalo em milésimos
    _timer.Elapsed += new System.Timers.ElapsedEventHandler(executarTarefa);
    _timer.Enabled = true;
}

static void executarTarefa(object sender, System.Timers.ElapsedEventArgs e)
{
    _timer.Enabled = false;
    // Seu código
    _timer.Enabled = true;
}

Don’t forget the property AutoReset, 'cause if she’s like true, it will perform only once, as described in your question.

  • Thanks, I did not know this to Autoreset, helped a lot =)

  • 2

    It would be interesting in the execution of the event executarTarefa disable the timer at the entrance. This prevents that for example, if the action takes more than 10 seconds and depends on status (example send emails to those who have not received them yet), these emails will be sent again if the status has not changed.

0

I understand you’re open to options, so follow one more:

Topshelf

It creates a very simple environment to create Windows Services with timers.

Just install Topshelf Nuget Package in your project Console Application:

Install-Package Topshelf

Then, in a very elegant way, create your service:

public class Program
{
    public static void Main(string[] args)
    {
        HostFactory.Run(configurator =>
        {
            configurator.Service<MeuServicoPeriodico>(s =>
            {
                s.ConstructUsing(name => new MeuServicoPeriodico());
                s.WhenStarted((service, control) => service.Start(control));
                s.WhenStopped((service, control) => service.Stop(control));
            });
            configurator.RunAsLocalSystem();
            configurator.SetDescription("Sobre meu serviço periódico");
        });
    }
}

Then create the container that will fire and control the lifecycle of your service:

public sealed class MeuServicoPeriodico: ServiceControl
{
    private readonly CancellationTokenSource _cancellationTokenSource;

    public MeuServicoPeriodico()
    {
        _cancellationTokenSource = new CancellationTokenSource();
    }

    public bool Start(HostControl hostControl)
    {
        Task.Run(() =>
        {
            while (true)
            {
                // Funções do seu aplicativo vão aqui

                Thread.Sleep(TimeSpan.FromSeconds(5));
            }
        }, _cancellationTokenSource.Token);

        return true;
    }

    public bool Stop(HostControl hostControl)
    {
        _cancellationTokenSource.Cancel();
        _cancellationTokenSource.Dispose();
        return true;
    }
}

Yes, it uses the "concept" of while-true-sleep, but this loop is in a task where your service has full control over its life cycle. Can pause, stop and restart from the Windows service panel - or left from anywhere else that can manage services.

See more details in this article on how to create Windows Service with Topshelf.

Official website Topshelf.

-2

I’ve used Timers, for me it worked, here an example of code:

Timer timer = new Timer();
timer.Interval = 1000; //1000 milésimos = 1 segundo
timer.Enabled = true;
timer.Elapsed += new ElapsedEventHandler(Time_Elapsed);

Now just create the Event Handler and put inside it what you want:

private void Time_Elapsed(object sender, ElapsedEventArgs e)
{
    //Alguma coisa
}

Note: Remember to put the using System.Timers;

  • It is worth remembering that if the property AutoReset is true, it will run "Something" only once.

  • But by default she is disabled is not even my dear?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.