vdt
vdt

Reputation: 11

C# - Stopping timer from another method

I'm trying to learn OOP with C#. Target framework: .net core 3.1. I have two classes. In the first one I initialize timer:

public class Test
{
    Timer timer = new Timer();
    public void Begin()
    {
        timer.Elapsed += new ElapsedEventHandler(Action);
        timer.Interval = 1000;
        timer.Start();
    }
    public virtual void Action(Object source, ElapsedEventArgs e)
    {
        Console.WriteLine("Running");
    }

    public void Finish()
    {
        timer.Stop();
        timer.Dispose();
    }
}

and in the main class I have two methods for starting timer and for stopping timer

class Program
{
    static void Main(string[] args)
    {
        Start();

        ConsoleKeyInfo input;
        do
        {
            input = Console.ReadKey();
        } while (input.Key != ConsoleKey.Escape);

        Console.WriteLine("Stopping");
        Stop();
        Console.ReadLine();
    }

    static void Start()
    {
        Test a = new Test();
        a.Begin();
        Console.WriteLine("Started");
    }

    static void Stop()
    {
        Test a = new Test();
        a.Finish();
        Console.WriteLine("Stopped");
    }
}

Why the timer keeps running after it is stopped and disposed?

Upvotes: 0

Views: 394

Answers (1)

Jaskier
Jaskier

Reputation: 1095

You're very close! As Chamika pointed out in the comments, you're interacting with two different instances of your Test class. The new keyword means just that, a new instance is created of Test.

To correct this, you can create either a global variable or pass the instance to your Start() and Stop() methods.

First, I'm going to show the global variable solution.


Without editing your Test class, I've modified your Program class. I've created a global variable: myTimer. myTimer is set to a new instance of the Test class. I also removed the other instance creations from your Start() and Stop() methods. Because they are in the same Program class, they will be able to interact with your global variable whether it's set to public or private!

    class Program
    {
        // Global variable to use within the class. 
        //  - This maintains the correct/same instance of the Test() class 
        //  - to interact with, starting/stopping.
        public static Test myTimer = new Test();

        public static void Main(string[] args)
        {
            Start();

            ConsoleKeyInfo input;
            do
            {
                input = Console.ReadKey();
            } while (input.Key != ConsoleKey.Escape);

            Console.WriteLine("Stopping");
            Stop();
            Console.ReadLine();
        }

        static void Start()
        {
            // I removed the Test a = new Test() line as it creates 
            // - a 'new' instance of the Test() class

            // Set the instance to interact with to the global variable: myTimer
            myTimer.Begin();
            Console.WriteLine("Started");
        }

        static void Stop()
        {
            // I removed the Test a = new Test() line as it creates 
            // - a 'new' instance of the Test() class

            // Set the instance to interact with to the global variable: myTimer
            myTimer.Finish();
            Console.WriteLine("Stopped");
        }
   }

// Output:
//  Started
//  Running
//  Running
//  Running
//  ... 
//  Stopping
//  Stopped 

Here is the passing variable solution just for another way to think about it!

About the same amount of changes are made, just in a different manner. The Test class is still not been touched or altered.

Instead of creating a global variable, add the arguments to your methods so they expect an instance of Test to be passed. Create the instance within your Main method and then pass the variable.

    class Program
    {
        public static void Main(string[] args)
        {
            // Create the instance of the 'Test' class. 
            // Since this is created in the 'Main' scope, passing it to 
            // Start() and Stop() will use this instance.
            Test myTimer = new Test();

            // Pass 'myTimer' to Start() to start timer
            Start(myTimer);

            ConsoleKeyInfo input;
            do
            {
                input = Console.ReadKey();
            } while (input.Key != ConsoleKey.Escape);

            Console.WriteLine("Stopping");
            // Pass 'myTimer' to Stop() to stop timer
            Stop(myTimer);
            Console.ReadLine();
        }

        static void Start(Test myTimer)
        {
            myTimer.Begin();
            Console.WriteLine("Started");
        }

        static void Stop(Test myTimer)
        {
            myTimer.Finish();
            Console.WriteLine("Stopped");
        }
  }

// Output:
//  Started
//  Running
//  Running
//  Running
//  ... 
//  Stopping
//  Stopped 

Upvotes: 4

Related Questions