VB Logo

Interrupting Events


The Problem

On occasion there are the odd problem or two which can easily be solved using traditional BBC Basic but which Visual Basic and its event-driven nature makes frustratingly difficult. For example, take the example of any process which the programmer doesn’t know how long it will take to complete. In this sort of situation it is impossible to show any kind of status bar to inform the user of the program’s progress. Instead what would be better is the addition of some sort of stop button or <Escape> key the user could press if the program was taking too long. However, for those who are thinking ahead on this problem will realise, whatever method the programmer uses to interrupt the main process it itself will rely upon an event. This is the crux of the matter: no event can be processed until one which is currently being executed has finished.

As already stated, solving many problems in Visual Basic is relatively easy, but there are others that at first glance seem almost impossible like the following example. This is a mathematical problem which the author of this site saw on TV but forgot to remember how many iterations it took. He thus decided some sort of ‘stop’ or ‘pause’ button might be nice to added to the application in case the program took hours. The problem consists of a large grid of squares all the same colour (lets say white) and is was used to demonstrate that chaos can result from what seem like very simple rules (listed below). The squares do start to form a pattern eventually but a surprising number of iterations are needed.

  1. Invert the colour of the current square
  2. Move one square forwards
  3. If the colour of the new square is white then turn clockwise 90 degrees
  4. If the colour of the new square is black then turn anti-clockwise 90 degrees

To demonstrate how the rules work the figures below show the first eight iterations (32 rules executed in total). The solution starts on the centre square and initiates the first rule - invert the colour of the current square. Here we will use a dark grey to show the inverted colour. The direction, as set by the red arrow is up, so moving one square forwards leads to a square on the top row. Next the new square is white and so the arrow turns clockwise 90 degrees. The square was white and so we ignore the forth rule. One whole iteration has now been completed. As you can see, the solution spirals clockwise inverting squares until the beginning of iteration 5 when the centre square is reached again. Here the forth rule comes into effect and the arrow turns anti-clockwise. The big question is - how many iteractions are needed before a pattern starts to form?

1.     2.     3.     4. 

5.     6.     7.     8. 

When designing a computer solution to this problem it is a good idea to use a single pixel for each square it makes the code simpler.


Solution #1 - the Timer

A first glance at the problem and many VB programmers will suggest using a Timer for each iteration. This effectively takes the solution out of some sort of repeating structure placed in the Click event of a ‘Start’ command button and puts the code into the Timer event. The problem is that even on the fastest Timer setting (Interval = 1) the solution is quite slow - about 9 minutes 45 seconds. The trouble is that there is a large overhead associated with managing and calling Timers in VB. As a solution to this ‘overhead’ problem, more instructions can be executed per timer tick. A For... Next loop set to 100 reduces the time until a pattern emerges to about 5 seconds. Although this new solution time is acceptable, it is bad programming because it relies upon the timer. The problem is that time is a fixed quantity and so the program will never complete is few than 5 seconds even given a 533MHz Alpha machine.


Solution #2 - DoEvents

Although the Timer solution can work it is not an elegant solution. Are there any alternatives? Well Visual Basic provides a special command called DoEvents which is specially designed to pause executing any current events and to process any events waiting in the queue. It is thus possible to place all the code to solve the problem inside one repeating structure and attach it to the Click event of a command button. The DoEvents command is then placed within the loop. A ‘Stop’ command button can be added to the project which sets a Public variable which is then checked by the solution loop to terminate. To make the program as fast as possible the DoEvents will be called only every 100 iterations (see line below), this will minimise any overheads associated with calling the command.

  If counter Mod 100 = 0 Then DoEvents

Using the DoEvents method brings down the time to about 3 seconds on a 233MHz Pentium PC. The advantage of this particular solution is that the speed of the program will increase with faster processors.

The screen shot below shows the final interface complete with Stop button. The mess in the middle is the pattern after 5,000 iterations. The usual Microsoft grey background has been chosen for the form instead of black. The exact colours do not matter as long as there are two different ones to invert between.


Additional Tips

  1. The command to test the colour of a single pixel on a form is Point. The example below shows the code to invert the colour of a pixel between grey (12632256) and white (0).

        If frmMain.Point(positionX, positionY) = 12632256 Then
         frmMain.PSet (positionX, positionY), 0
        Else
          frmMain.PSet (positionX, positionY), 12632256
        End If
    
  2. As the code above shows, the corresponding command to set the colour of a single pixel is PSet.

  3. When testing and setting the colours of individual pixels directly on a form is it useful to set the AutoRedraw property of the form to True. If set to False and another window covers the form or a screen saver starts during program execution the squares will not be redrawn and the solution destroyed.



Menu