Implementing a Flashlight-Finder Feature Using Threads


Next, we are going to improve our flashlight by adding a finder feature. This is to help users who have problems finding the flashlight in the dark (which is hardly surprising). The addition to the flashlight will cause the lamp to flash for half a second every two minutes. If we need to find the flashlight in the dark, we now just have to wait for a little while until it signals where it is.

Foreground and Background Threads

At the moment, our program contains multiple threads of execution. A thread is created each time an interrupt is required. In addition, we have the original foreground thread that forms the body of the Main method. We can add our flashlight-finder feature by making use of this thread. Because we attached the on/off behavior to interrupts, the main thread now has nothing to do and contains just a call to the Sleep method. Instead of this, we can create a loop that waits for a while and then flashes the lamp for half a second.

 while (true) {      // Wait for 5 seconds      System.Threading.Thread.Sleep(5000);      if (switchInterrupt.Read())         // go round again if the switch is on         continue;      // Switch on the lamp      lampOutput.Write(true);      // Wait for a 10th of a second      System.Threading.Thread.Sleep(100);      // if the switch is not on, turn the lamp off      if (!switchInterrupt.Read())      {         lampOutput.Write(false);      } } 

This loop performs a timed sleep. It then checks to see whether the switch is on, that is, the flashlight is lit. If it is, the continue will cause the loop to go back to the top and wait another five seconds. Otherwise, the lamp is turned on, the program sleeps for a tenth of a second, and then the lamp is turned off. This will cause the lamp to flash briefly every five seconds. At the end of the flash, if the switch has not been turned on, the program turns the lamp off.

This code seems to work well, but when the customers start using the super flashlight, they report problems. They claim that every now and then the flashlight does not switch on when they press the button.

The problem is caused by an interaction between the two threads that are sharing the same inputs and outputs. If the user manages to turn the flashlight on just at the end of a finder flash-that is, in the time between the test to see whether the switch is on and the line that turns the lamp off-the code will turn the lamp off even though the user has closed the switch.

 if (!switchInterrupt.Read()) {    System.Threading.Sleep(500);    lampOutput.Write(false); } 

The Sleep statement is where the glitch occurs, and it makes the problem very obvious. All the user has to do is wait for the finder flash and then close the switch. When the flash ends, the flashlight is turned off, giving the fault as reported by our users.

Thread Synchronization

What is needed is a way of ensuring that it is not possible for the interrupt handler to change the lamp state until the test and set have been performed. Fortunately, the .NET Framework provides this facility in the form of Monitors. The monitor mechanism uses a synchronization object that is shared between the threads that need to synchronize. The object can be an instance of any C# class, so we can use the switchInterrupt item.

 System.Threading.Monitor.Enter(switchInterrupt); if (!switchInterrupt.Read()) {    lampOutput.Write(false); } System.Threading.Monitor.Exit(switchInterrupt); 

Once the code has performed the Enter method, it has control of the synchronization object, and any other thread calling the Enter method on this object will be held until the Exit method is called. If the interrupt handler has corresponding behavior, the two threads have no chance of conflicting.

 static void switchInterrupt_OnInterrupt(Cpu.Pin port, bool state, TimeSpan time) {    Monitor.Enter(switchInterrupt);    lampOutput.Write(state);    Monitor.Exit(switchInterrupt); } 

Now, it is impossible for the interrupt handler to run in between the test for the switch state and the act of turning the light off. So, if an interrupt occurs during that time, the handler will be held until the lamp has been switched off. Then, when the handler runs, it will switch it on again, removing the glitch.

Note 

It is important to remember that while a thread has a lock on a synchronization object, it may be blocking other threads from running. For this reason, make sure you release locks as quickly as possible.

Creating Threads

The flashlight program has two threads, but one of them is in the body of the Main method. Although this will work well, situations might arise in which more than one thread is required, and from a design perspective it might be considered cleaner to create a separate thread to execute the flashlight-finder feature. The first thing to do is program the flashlight-finder feature in a method.

 private static void finderFlash() {    while (true)    {       // flashlight-finder feature goes here    } } 

The Main method can now create a thread instance and start it. The constructor of the thread receives the method to be executed in the thread. Once the thread instance has been created, it can then be started by calling its Start method.

 System.Threading.Thread finderThread = new Thread(finderFlash); finderThread.Start(); 

Note 

It is important that any threads you create behave themselves. By this we mean that if they do not yield the processor by making calls to Sleep, they could cause performance problems in other threads.




Embedded Programming with the Microsoft .Net Micro Framework
Embedded Programming with the Microsoft .NET Micro Framework
ISBN: 0735623651
EAN: 2147483647
Year: 2007
Pages: 118

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net