I've been reading Illustrated C# 2008 by Daniel Solis (an excellent book, btw) and decided to spend a little more time on Events to further my understanding of the topic. I'm trying to understand why I'm seeing different results every time I run the program and what I might be able to learn from this.
(Source Code Below) In the sample code in the book, there's a MyTimerClass which has an event which is subscribed to System.Timers.Timer. There are two other classes, ClassA and ClassB, both which have Event Handlers (one is static while the other is not) that write to the console. In the main function of the program, the event handlers of those classes are tied up to an event in an instance of the MyTimerClass. Another function is added to the event member via a lambda expression.
After working with the author's code, I decided to add another class, ClassC. Rather than add the event handler within the Main function of the program, I instead decided to create a separate MyTimerClass object within ClassC's constructor that then subscribed to MyTimerClass's event.
When I ran my code for 4.25 seconds on 3 separate occasions, my results were always in a different order. The Event from the Main function of the order always invoked ClassA, ClassB, then Lambda in the same order. However, the other event for ClassC always seems to be invoked in a completely random order. I also notice that the first group of method calls seems to have slightly different times, while the subsequent groups all have the same times. Why is that?
(1) Event 1 - ClassA - 51:259
Event 2 - ClassC - 51:259
(2) Event 1 - ClassB - 51:261
(3) Event 1 - Lambda - 51:262
(1) Event 1 - ClassA - 52:271
(2) Event 1 - ClassB - 52:271
(3) Event 1 - Lambda - 52:271
Event 2 - ClassC - 52:271
(1) Event 1 - ClassA - 53:285
(2) Event 1 - ClassB - 53:285
(3) Event 1 - Lambda - 53:285
Event 2 - ClassC - 53:285
(1) Event 1 - ClassA - 54:299
(2) Event 1 - ClassB - 54:299
(3) Event 1 - Lambda - 54:299
Event 2 - ClassC - 54:299
(1) Event 1 - ClassA - 17:30
Event 2 - ClassC - 17:30
(2) Event 1 - ClassB - 17:32
(3) Event 1 - Lambda - 17:33
(1) Event 1 - ClassA - 18:42
(2) Event 1 - ClassB - 18:42
(3) Event 1 - Lambda - 18:42
Event 2 - ClassC - 18:42
(1) Event 1 - ClassA - 19:56
(2) Event 1 - ClassB - 19:56
(3) Event 1 - Lambda - 19:56
Event 2 - ClassC - 19:56
Event 2 - ClassC - 20:70
(1) Event 1 - ClassA - 20:70
(2) Event 1 - ClassB - 20:70
(3) Event 1 - Lambda - 20:70
(1) Event 1 - ClassA - 45:220
Event 2 - ClassC - 45:221
(2) Event 1 - ClassB - 45:223
(3) Event 1 - Lambda - 45:223
(1) Event 1 - ClassA - 46:232
(2) Event 1 - ClassB - 46:232
(3) Event 1 - Lambda - 46:232
Event 2 - ClassC - 46:232
Event 2 - ClassC - 47:246
(1) Event 1 - ClassA - 47:246
(2) Event 1 - ClassB - 47:246
(3) Event 1 - Lambda - 47:246
(1) Event 1 - ClassA - 48:260
(2) Event 1 - ClassB - 48:260
(3) Event 1 - Lambda - 48:260
Event 2 - ClassC - 48:260
Here's the source code for my Console Application:
class Program
{
static void Main(string[] args)
{
MyTimerClass mc = new MyTimerClass();
ClassA ca = new ClassA();
ClassC cc = new ClassC();
mc.MyElapsed += ca.TimerHandlerA;
mc.MyElapsed += ClassB.TimerHandlerB;
mc.MyElapsed += (obj, e) =>
{
Console.WriteLine("(3) Event 1 - Lambda - {0}:{1}",
System.DateTime.Now.Second,
System.DateTime.Now.Millisecond);
};
Thread.Sleep(4250);
}
}
class ClassA
{
public void TimerHandlerA(Object obj, EventArgs e)
{
Console.WriteLine("(1) Event 1 - ClassA - {0}:{1}",
System.DateTime.Now.Second,
System.DateTime.Now.Millisecond);
}
}
class ClassB
{
public static void TimerHandlerB(Object obj, EventArgs e)
{
Console.WriteLine("(2) Event 1 - ClassB - {0}:{1}",
System.DateTime.Now.Second,
System.DateTime.Now.Millisecond);
}
}
class ClassC
{
public void TimerHandlerC(Object obj, EventArgs e)
{
Console.WriteLine(" Event 2 - ClassC - {0}:{1}",
System.DateTime.Now.Second,
System.DateTime.Now.Millisecond);
}
public ClassC()
{
// This will create a separate MyTimerClass and
// attach ClassC's event handler to mc's event.
MyTimerClass mc = new MyTimerClass();
mc.MyElapsed += TimerHandlerC;
}
}
public class MyTimerClass
{
public event EventHandler MyElapsed;
private void OnOneSecond(Object obj, EventArgs e)
{
if (MyElapsed != null)
MyElapsed(obj, e);
}
private System.Timers.Timer MyPrivateTimer;
public MyTimerClass()
{
MyPrivateTimer = new System.Timers.Timer();
// This will attach the OnOneSecond Event Handler
// to the system timer which will then raise
// MyElapsed.
MyPrivateTimer.Elapsed += OnOneSecond;
// This sets the interval at 1 second.
MyPrivateTimer.Interval = 1000;
// This turns the timer on when the the class
// is instantiated.
MyPrivateTimer.Enabled = true;
}
}
Three questions:
- Why is it that the results are different every time and what is causing that to happen?
- Why are the times in the first block of results slightly off while the subsequent blocks have the same times?
- What should I learn from this example?