Time Events

Another excellent tool to enhance your UX are events triggered by time. These can give your software a greater sense of sentience and promote proactive engagement with the user. You can also use this for specific time sensitive events to occur. One example of this came to me recently when I was trying to buy movie tickets online to see Deadpool 2 (way to date when you wrote these notes, Daniel...). Once seats in the theater were selected, there was a limited amount of time to complete the purchase, before the server terminated the transaction and re-opened those seats for reservation. This could be trivially accomplished using a System.Windows.Forms.Timer that would be initialized to 0 when the "Enter Purchase Information Here" form was presented, then triggered when X number of seconds had elasped, automatically loading up the "Sorry, you took too long!" page.

It's important to distinguish between System.Windows.Forms.Timer and System.Timers.Timer, which not only share a similar name — love that... — but have a critically different implementation. The SWFT version attaches itself to your Form, allowing you access to your components and methods defined within your Form1 class, while the STT version is statically allocated and therefore requires some trickery to interact with your Form — if it can at all. Visual Studio 2017 allowed me to use the STT version in the past, which was great because of the addition of the ElapsedEventArgs for exam questions, but I believe 2019 put it's foot down and declared this to be "cross-thread hazardous". So I'm updating these notes accordingly, while keeping the other version for posterity.

Here's a simple example of how to update a Label every second.

public static System.Windows.Forms.Timer myTimer;
public static int counter = 0;

public Form1()
{
InitializeComponent();

myTimer = new System.Windows.Forms.Timer(); // Interval set to 10 seconds

myTimer.Enabled = true;
myTimer.Interval = 1000; // measured in milliseconds
myTimer.Tick += new EventHandler(UpdateLabel);
}

private void UpdateLabel(object source, EventArgs args)
{
Time_Label.Text = "Counter == " + ++counter;
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
myTimer.Dispose();
}

There's also the StopWatch class, whose objects are used to function very much like like the stop watches of the physical world. You create a StopWatch object, call the Start() method, followed by Stop(), then measure the Properties of the StopWatch such as public TimeSpan Elapsed, where TimeSpan has Days, Hours, Minutes, and Seconds Properties, and public long ElapsedMilliseconds, to simply get the number of milliseconds recorded. There's also a public bool IsRunning Property.

Previously

The data available from MouseEventArgs and ElapsedEventArgs together could draw a detailed recreation of user interactions with software, perhaps in an effort to determine where improvements to the UI could be made so users more easily find what they're looking for... but also to gather data points about you that can be fed into prediction software to determine what kind of products you're going to want to buy from Amazon at 11:25pm on a Friday night, after you've spent 20+ minutes looking through your ex's profile on Facebook. </tinfoil hat>. (... But is it really too crazy to think that this is happening to us online?)

Let's shift gears and look at the actual implementation of these timed events, starting with a Timer. These objects tick in real time, measured by milliseconds, and broadcast an Elapsed event once the number of measured ticks reaches a programmer-defined Interval, a double property of Timers. You can configure the Time to trigger this event only the first time this Interval has been reached, or have it reset and repeat it for every Interval number of milliseconds have passed. You will want to Dispose of Timers once you finish with them, either by calling the method directly inside of a try/catch block, or by using the... using mechanism.

public static void Main()
{
private static void MyTimedEvent(object source, ElapsedEventArgs args)
{
Console.WriteLine("Another 10000 milliseconds have elapsed at {0:HH:mm:ss.fff}", arg.SignalTime);
}

using (Timer myTimer = new Timer(10000)) // Interval set to 10 seconds
{
myTimer.Elapsed += MyTimedEvent;
myTimer.AutoReset = true; // Makes it repeat
myTimer.Enabled = true;

  string slacker;
while (slacker != "q")
{
Console.WriteLine("\nEnter 'q' to quit the application: ");
slacker = Console.ReadLine();
}
}
}