-6

I'm trying to get this to run every 300ms but it doesn't run at all

var gametick = new System.Threading.Timer((e) =>
        {
          //stuff
        }, null, 0, TimeSpan.FromMinutes(Convert.ToDouble(300).miliseconds);

I don't know what to try but I am expecting to use this to add gravity to my character so every 300 ms he goes down one block but it didn't effect the game at all

3

2 Answers 2

1

There are actually couple of ways to achieve such goal.

There are couple of ways - using Timer, Thread or Task.

I won't focus on Thread as it's "old" approach to code parallelization and I try to avoid it. Task is the way to go in most cases and I will present that approach.

Without further ado, below is the code, with three methods, each containing different solution to your problem. Each has rich comment to explain what and how:

public class DoStuffPeriodically
{
    const int intervalMs = 300;

    public static void DoStuff() { }

    // Here you "do stuff", wait 300 ms and repeat the loop
    // after completion.
    // NOTE: DoStuff does not happen every 300ms, the timeline is:
    // do stuff (for some milliseconds, maybe 100), wait 300ms and repeat.
    // So another DoStuff will begine 400ms after first.
    public static async Task FirstApproach()
    {
        while (true)
        {
            DoStuff();
            await Task.Delay(intervalMs);
        }
    }

    private static readonly List<Task> tasks = new List<Task>();

    // Here you "do stuff" in a Task, which allows not waiting for it,
    // but storing reference to "that processing" and await it later.
    // NOTE: DoStuff does happens every 300ms, the timeline is:
    // start doing stuff and immediiately wait 300ms and repeat.
    public static async Task SecondApproach()
    {
        while (true)
        {
            tasks.Add(Task.Run(DoStuff));
            await Task.Delay(intervalMs);
        }
        
        // remember to await all the remaining tasks in "tasks" array.
        await Task.WhenAll(tasks);
    }

    // Using a timer, classic approach.
    public static void ThirdApproach()
    {
        // Create a timer with a two second interval.
        var aTimer = new System.Timers.Timer(intervalMs);
        // Hook up the Elapsed event for the timer. 
        aTimer.Elapsed += (o, e) => DoStuff();
        aTimer.AutoReset = true;
        aTimer.Enabled = true;

        // Here code execution continues, you have to block the program
        // from running to completion to keep timer alive, for example
        // in console app you could do this:
        Console.WriteLine("\nPress the Enter key to exit the application...\n");
        Console.ReadLine();

        // After using timer, stop it and dispose it.
        aTimer.Stop();
        aTimer.Dispose();
    }
}
-2

This is console app to demonstrate a fix for your issue. Play method is being invoked each 300ms, where purpose of while is just to keep console app running so that you can see log statements in console and delay is added only to show console log appropriately. The code is from program.cs file for .NET 6 Console app project. If things are not clear then please raise question. I have tested its working.

int count = 0;

var gametick = new System.Threading.Timer((e) =>
{
    Play();
}, null, 0,  300U);

Console.WriteLine("Hello, World!");
while (true)
{
    Console.WriteLine($"In while loop");
    await Task.Delay(5000);
}

void Play()
{
    count++;
    Console.WriteLine($"Play {count}");
}

By running this you can see that following code is working fine as required.

var gametick = new System.Threading.Timer((e) =>
{
    Play();
}, null, 0,  300U);

Not the answer you're looking for? Browse other questions tagged or ask your own question.