0

Im trying to write a console app where i am supposed to run a simulation for a daycare for hamsters. The task is to make them arrive, putting them in cages, girls with girls and boys with boys. There are 30 hamsters each day. I have a method that lets them get out and play, I want to call this method every hour. Im having a hard time getting timers, events etc to work. Can someone please help me get started? They are all arriving at 07.00 every morning, so the time is not DateTime.Now, more like DateTime.Now.Date.Add(new TimeSpan(7,00,0)); for the sake of the task. The methods are no problem but cant get it to work.

They are supposed to be in the daycare from 07 - 17.00, 10 hours.

var count = DateTime.Now.Date.Add(new TimeSpan(7, 00, 0));
        for (int i = 0; i < 100; i++)
        {
          count += TimeSpan.FromMinutes(6);
        }

Do anyone have any suggestions? Or if you need more info just let me know! Thanks guys!

Mangaz
  • 21
  • 7
  • 1
    Check this thread, I think this is what you need [timer on c#](https://stackoverflow.com/questions/13019433/calling-a-method-every-x-minutes) – kaan Apr 02 '21 at 14:03
  • For debugging, use a time of 10 seconds instead of one hour to make it easier to find issue. – jdweng Apr 02 '21 at 14:05
  • Thanks Kaan I will check it out, should I start the timer in the for loop? One day at the daycare is 10 hours, like in my for loop, how can I call the method in the for loop? Should I t.Start() in the loop? I will try some but if you have any good examples Im all ears, also, i will check out the link! – Mangaz Apr 02 '21 at 15:15
  • You just start a timer once, and it will run in it's own thread, and will automatically execute some code (like calling a method) at a specified interval. This acts as a "loop", so you can just "fire and forget". The code that's executed would then check take some action if needed. These checks and actions can be encapsulated in methods, i.e: `if (HamstersShouldBeInCages(currentTime)) PutHamstersInCages(); else if (HamstersShouldBeOutside(currentTime)) PutHamstersOutside();`, etc. See [Timer Class](https://docs.microsoft.com/en-us/dotnet/api/system.threading.timer?view=net-5.0) for more info. – Rufus L Apr 02 '21 at 18:00

2 Answers2

0

You can use a System.Threading.Timer to run some action at a specified interval. This action can be to check the current time and then ensure the hamsters are where they need to be at that time. You only need to set the timer and it's interval (i.e. how often you want it to check on the hamsters) and then it will act like a "loop", so you can just "fire and forget".

See Timer Class for more info.

The code below is an example of one way to do it. For debugging I've used a very small window between when they should be in thier cages and when they should be outside (in cages at the start of each minute for 5 seconds, then outside for 10 seconds, then inside for 5, etc.), but in your "real world" example you would change it to: if (currentTime.Hours >= 7 && currentTime.Hours <= 17)

private static TimeSpan TimeDiff;

public static void Main()
{
    // Pretend it's 7:00 when the app is started by storing the time 
    // difference so it can be subtracted later when comparing times
    TimeDiff = DateTime.Now.TimeOfDay - new TimeSpan(7, 0, 0);

    var timer = new System.Threading.Timer(
        e => UpdateHamsters(),            // The method to execute each interval
        null, 
        TimeSpan.Zero,                    // How long to wait before the first execution
        TimeSpan.FromSeconds(1)           // How long to wait between intervals
        );
}

public static void UpdateHamsters()
{
    // Subtract the time differnce to get adjusted time
    var currentTime = DateTime.Now.TimeOfDay - TimeDiff;
    var timeString = currentTime.ToString(@"hh\:mm\:ss");

    // Adjust as necessary for debugging
    if ((currentTime.Seconds > 5 && currentTime.Seconds <= 15) ||
        (currentTime.Seconds > 20 && currentTime.Seconds <= 30) ||
        (currentTime.Seconds > 35 && currentTime.Seconds <= 45) ||
        (currentTime.Seconds > 50))
    {
        // Code to ensure hamsters are outside
        Console.WriteLine($"{timeString} - All hamsters are outside.");
    }
    else
    {
        // Code to ensure hamsters are in cages
        Console.WriteLine($"{timeString} - All hamsters are in cages.");
    }
}
Rufus L
  • 36,127
  • 5
  • 30
  • 43
  • Ahh okay! For the task I have, all hamsters are suppose to check in at 07.00 in the morning, and go home at 17.00, so even if real time is 12, their time will be 07.00 when i start my console app, what is a good way to check my methods/timers against that arrival time? Create a variable that holds the time 07 and like variable.FromMinutes(6) in a loop and check against my method/timer? Let me know if my explanation is so so :'D – Mangaz Apr 02 '21 at 19:12
  • I don't understand why you have a "real time" and "their time", but I would just create a `DateTime` that holds the time difference between the two and add that to the current time before checking. – Rufus L Apr 02 '21 at 19:28
0

Ahh, okay thanks for input. I have been trying this method for a while now and I cant get it to work, or, I mean, it does somewhat right, 6 hamsters goes ut at a time, but when there are 3 male hamsters left, then 3 female hamsters are getting added in. And this is my biggest problem.

public static void ThreadLetHamstersPlay()
    {
        lock (hamsterLock)
        {
            using(var db = new HamsterContext())
            {
                int hamstersInExercisearea = 0;
                var availableSpaceInExerciseArea = db.ExerciseArea.Where(EA => EA.AvailableSpace == true).ToList();
                var getHamster = db.Hamsters.Where(H => H.Activity == null).ToList();

                int maxLimit = availableSpaceInExerciseArea.Count <= getHamster.Count ? availableSpaceInExerciseArea.Count : getHamster.Count;

                for (int i = 0; i < maxLimit; i++)
                {
                    if (getHamster[i].Gender == "Male")
                    {
                        getHamster[i].Activity = DateTime.Now;
                        db.SaveChanges();
                        availableSpaceInExerciseArea[i].AvailableSpace = false;
                        getHamster[i].ExerciseAreaID = availableSpaceInExerciseArea[i].ExerciseAreaID;
                        hamstersInExercisearea++;
                        Console.WriteLine($"{getHamster[i].Name} is out playing right now. . . Gender - {getHamster[i].Gender}");
                    }
                    
                    Thread.Sleep(1000);
                    db.SaveChanges();
                }
            }
        }
    }

Now I only check for the male, how can I keep the females away until the males are done? Just changed the method a little after your input :)

Mangaz
  • 21
  • 7