Page 2 of 4
Now we have the basic structure needed to setup the application and start the timer running. Everything that the application does from this point on is concentrated in the timer routine. It’s a good idea to give the user some feedback on what is going on so add a TextBox to the form and set it to multiline with a single vertical scrollbar. We can now post a message each time the timer event handler is called:
private void timer1_Tick(object sender,
textBox1.Text += "Update at:" +
If you run the program as it stands you will see the “Update at” message appear at the set interval. Time to make it do a little more!
For each of the rows of the grid that contain a valid address we have to ping the server. The simplest way of doing this is to use a foreach loop and so the timer tick method continues:
foreach (DataGridViewRow row
if (row.Cells["Address"].Value != null)
Now we are ready to ping the server and to do this we assume that there is a method that will accept the address, a retry and pause specification.
The retry is simply the number of times to ping in the case of a failure and the pause is the time in seconds to leave between each attempt. Some servers go to sleep if they are not being used so an initial ping might well fail for this reason. However, there isn’t much point in trying to ping the server immediately after it has failed to respond because it needs time to wake up – hence the need for a pause between pings. In this case we are providing a single value for both the retry and the pause to be used with all of the servers in the list. If you want to be more flexible you could store values to suit each server to be tested in additional columns in the grid.
Next we actually perform the ping:
PingReply reply = DoPing(
The DoPing method is something we will write later and it could easily be replaced by a DoWebPage method if you want to test to see if a web page is available or a more general DoProtocol method.
The DoPing method returns a PingReply object which contains the result of the ping. To make use of the ping facilities that .NET 2.0 provides we have to add to the start of the program:
Now we can transfer the Status and Time property in the PingReply object to the grid to provide the user with feedback on what happened.
All that remains is to create the DoPing method. First we need to create a suitable Ping object and PingReply variable:
private PingReply DoPing(
Ping pinger = new Ping();
We now try the ping the number of times specified by retry:
for (int i = 1; i <= retry; i++)
The Send method comes in a number of different forms and there is also an asynchronous send method which returns immediately. The “blocking” Send is much easier to use but it halts the execution of the program until the server replies or times out. You can set the timeout to something other than its default five seconds using one of the other versions of the Send method. If the reply is successful we simply bring the for loop to an end:
if (reply.Status == IPStatus.Success)
Otherwise we wait for the specified pause time and try again or simply end the loop and return the result:
Notice the way that the pause is implemented by putting the current thread to sleep. This is generally a good way of implementing a pause because it gives other processes the opportunity to run and hence it’s efficient. To use the Thread object we need to add to the start of the program:
If you now run the program and click the Start Scan button you should see the status of all of the sites listed change at the update interval. At this point it is worth adding another button labelled “Stop Scan” with event handler:
private void button2_Click(
object sender, EventArgs e)
timer1.Enabled = false;
The overall user interface should now look something like the one shown here.
The user interface
There is one subtle point to keep in mind when using a Timer component to generate regular events.
A Timer component uses the same thread of execution that the user interface, i.e. the form that the Timer component is placed on, uses to update itself.
This makes programming simple because the timer Tick event handler can access the components on the form without having to worry about issues of “cross thread” programming. There are alternative timers that use their own thread of execution and these are more accurate and flexible but more difficult to use in conjunction with a form. The biggest problem with using a Timer component is that while the Tick event handler is executing the user interface provided by the form is frozen.
In this case the Tick event doesn’t take long to process and the “freeze” is mostly acceptable. If the freeze becomes unacceptable then you can either switch to using one of the other Timer objects that .NET offers or you can put:
at any point in the Tick event handler to allow the user interface to run.