Reputation: 11
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
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