Iterators are useful, but prior to C# 2.0 they have been a bit of messy to write. Say you have always needed an extra class in the past to store the state of where you are in the collection currently. yield statements allow you to write iterators "inline" in a single method, with the compiler doing all the hard work of keeping track of state behind the scenes. yield statements are only valid in a method, operator or property which returns one of IEnumerable or IEnumerator. There are two types of yield statements; yield return for returning the next item and yield break to mark the end of the iterator. With yield statements, the compiler effectively builds a state machine. Every time MoveNext() is called on the iterator (e.g. by the foreach statement) execution continues from where it had been until it next reaches a yield statement.
Presented here is a class ClockSimulator which implements IEnumerable interface. In the method GetEnumerator(), yield statements are used to return the current tick as a string. It can be timed for a maximum of 24 hours. There is a flag called stop which an external program can use to stop the Clock. The yield break is used for this purpose which is useful if you want to stop iterating due to some external signal.
using System; using System.Collections; using System.Threading;
namespace ClassLibrary { public class ClockSimulator : IEnumerable { public volatile bool stop = false;
int sec = 0; int min = 0; int hr = 0;
#region IEnumerable Members
public IEnumerator GetEnumerator() { for (int i = 0; i < 24; i++) { for (int j = 0; j < 60; j++) { for (int k = 0; k < 60; k++) { Thread.Sleep(1000); // 1 sec is over if (stop) { yield break; } if (k + 1 == 60) { sec = 0; min = j + 1; if (min == 60) { min = 0; hr = i + 1; } } else { sec = k + 1; } yield return string.Format("{0:00}:{1:00}:{2:00}", hr, min, sec); } } } }
#endregion
public void Tick() { // This would keep going for a very long // time if the counter wasn't stopped! foreach (string count in this) { Console.WriteLine(count); //you may comment the following line if you don't want beep Console.WriteLine('\a'); } } } }
Here is a sample code which spawns a Thread to tick the Clock for a duration of 1 min 1 sec:
ClockSimulator clockSim = new ClockSimulator(); new Thread(new ThreadStart(clockSim.Tick)).Start(); // Tick for 1 min 1 sec Thread.Sleep(61000); clockSim.stop = true;
There is only one short coming in the ClockSimulator class. Since we are breaking after the specified amount of Thread Sleep time; the last tick won’t be reported. For example if you run this example ticks till 00:01:00 will be reported, although the Thread slept for 1 min 1 sec. There is another flip side of the ClockSimulator. We can expect some time loss in the arithmatic operations; looping; invoking Thread sleep etc. So; if this simulator is run for a very long time you may see some time loss. For example I timed the simulator for 1 hr 1 min 1 sec in the driver Thread; but I got ticks reported till 1 hr 42 secs.
|
No responses found. Be the first to respond and make money from revenue sharing program.
|