In one of our recent conversations together, I mentioned a “magic number”: 200-msec. You may recall that 200-msec is important because that is the amount of time that most people will wait before getting concerned that there is something wrong with the program they are using. To help address that (very-short) deadline, we created an architecture that implements a splash screen the point of which is to keep the users’ eyeballs busy while the application loads. The code works well “as is” for small fast-loading processes, but what about processes that might take several seconds to load? Or applications with a large number of processes that need to be launched?
This time out I want to look at a couple of techniques that will help in those more-demanding situations as well.
Spinning Cursors
In a the computer world, a universally-recognized way for a program to tell the user, “Wait a minute, I’m thinking” is the busy cursor. Whether a rotating hour-glass or a spinning wheel, people recognize the symbolism. To support this technique, LabVIEW will occasionally show the busy cursor on its own. However, these “automatic” cursor changes don’t always fall where we would like them, so LabVIEW also provides a set of VIs for managing cursors. The two basic VIs you will want to use are Set Busy.vi
and Unset Busy.vi
which allow you to turn the busy cursor on and off. Normally, you can just drop them down on a block diagram, wire-up the error clusters, and you’re good to go.
However, Set Busy.vi
has a couple optional inputs that can be useful in specific situations. For example, by default, the busy cursor displayed is the system default defined in your Windows display theme. However, you can also specify one of your own. The top-most terminal on the left side accepts a cursor reference that allows you display an alternative cursor. To derive this reference, the cursor palette also includes a function called Create Cursor From File.VI
that allows you to open .ani
or .cur
files.
The second terminal down the left side of Set Busy.vi
is for a VI reference. If left unwired, LabVIEW defaults to the current VI. This input is useful in situations where this subVI isn’t on the block diagram of the open window. However, it can also be handy if you should happen to have more than one window open, but you only want one of them to show as being busy.
Finally, the third terminal down is a Boolean input that allows you to force LabVIEW to continue to register mouse clicks while the cursor is showing busy. Again, you may not want to use this input all the time, but I have seen applications where you can abort a long process by clicking anywhere in the window. This input provides a mechanism for implementing that functionality. All you have to do is create a Mouse Up?
event on the front panel as a whole.
Changing Labels
As you would expect, people who begin to worry about system responsiveness after only 200-msec, can only stare at a spinning cursor for so long before they start to worry again. There are a variety of ways addressing this issue. Progress bars are nice, but can be a pain to create such that they update nicely. An alternative that I have used, that is easily expandable, is to simply take the name of the process being launched, strip off the file extension and put the rest in a string indicator on the front panel.
This approach has the added benefit of providing potentially useful troubleshooting information. For example, say your application really does lock-up or crash or something. The name on the screen tells you what it was trying to do when its world came to an end.
I have also modified this basic approach to make the indicator larger and give it a scrollbar. Then when updating it I prepend the new data to the beginning of what was already there. Now instead of simply showing the last process launched it will display a complete log of all the processes and the order in which they started — again a boon in troubleshooting. You could even pass a reference to the indicator to the processes so they can post information to it while they are initializing themselves.
In any case, here is what the launcher looks like after both of the modifications we’ve discussed (no SVN update this time):
One additional and interesting point that I want to point out is that if you compare this code to the previous release, you will notice that the delay following the launch is longer — in fact I doubled it. Why? Well, therein lies a bit of a paradox and its all about user perceptions. You see these same people that go through life with a 200-msec fuse on their patience also sometimes get unhappy if things happen too fast…
People don’t like it when things blip past too fast so I slow the loop down. As a customer once told me, this simple change gave him confidence that, “…the computer is really doing something…”. However, as illogical as that argument might seem, I didn’t complain. After all it set-up a situation where a couple months later one of the other users expressed a concern over how long it took to launch the application. Of course I was able to impress him greatly by being able to deliver an “optimized” version the very next day.
Yes, all I did was change the timeout; and no, I didn’t charge them.
Until next time…
Mike…