I can't make my script do nothing!

I can't make my script do nothing!

  • Comments 5

Yes, the title is grammatical. A few days ago I was discussing the semantics of data that isn't there. Today I want to talk a little about programs that do nothing. What do you do when you want a program to pause briefly, for whatever reason?


Those of you who like me cut your programming teeth on Commodore PET Basic know the answer. A for loop will do the trick.


for(x = 0 ; x < 1000000 ; ++x) {}


Of course, that has the problem that the time spent paused is shorter on faster machines.  The obvious improvement waits until a given number of milliseconds have passed:


for(var startTime = new Date(); new Date() - startTime > 1000 ; ) {}


The problem with both these techniques is that this is busy waiting.  The program may appear to be paused but it is actually executing as furiously as ever.  The processor is probably pegged to 100% but doing entirely pointless work.  In a multithreaded, multiprocess operating system busy waiting is downright rude -- the processor could be tending to other tasks like redrawing the screen or background processing.


Really what you want to do is to ask the operating system to put the process asleep for a bit and then wake it up later, right?  That way the program pauses but the thread scheduler is free to run something more important. And indeed, there's a Win32 API that does just that, Sleep.


But there is no way to call win32 APIs directly from script, so the scriptable "go to sleep" method needs to either be built in to the language, or (the horror!) in an ActiveX object. So why the heck do VBScript and JScript not have a "go to sleep" method built in? 


Well, actually, there were good reasons why we didn't. The principal reason is because I lied above.  You do NOT want to put the process to sleep and wake it up again later, because while the script is "sleeping", you still might want event handlers to run.


The way events work in Apartment Threaded COM objects such as initialized script engines (see my earlier entries for a refresher on how the script engine threading model works) is pretty simple. When the user clicks on a button and raises a button event, what actually happens is a bunch of messages are deposited in the thread's message queue.  When the message queue is pumped, the messages tell the COM plumbing to call the event sinks listening to the event sources.


So what happens when a thread is asleep?  No message loop runs on the thread!  How could it?  It's asleep.  So you put your script to sleep for ten seconds, a user presses a button, and then waits at least ten seconds for the message loop to get pumped?  That seems kind of suboptimal.  The sleep method needs to pump a message loop occasionally so that events get handled.


It gets worse.  What if one of those event sinks causes a script error, which is then reported to the host, and the host decides to shut down the script engine? Ten seconds later, the script wakes up and keeps running! Oh, the pain.


To properly implement a "go to sleep" method you need to know all kinds of details about the desired message processing, event handling, error handling and multi-threading semantics of the host application.  We were very worried that we'd add a method to the script engines which, when used in IE, or ASP, or WSH, or some third-party script host, completely screw up the carefully implemented host.


Hence, no "go to sleep" method in the languages.  If the host implementor thinks that a "go to sleep" method is necessary, they can implement one and add it to their object model, as we did for WSH.

  • Hey Eric, We use this "trick" to mimic a non-CPU intensive delay in our scripts and it does allow event handling on the main thread (or at least databinding which is our main concern). function sleep(numberMillis) { var dialogScript = "window.setTimeout(" + " function () { window.close(); }, " + numberMillis + ");"; var result = window.showModalDialog("javascript:document.writeln(" +" '<script>" + dialogScript + "<" + "/script>')"); }
  • Indeed, that is another good example of what I'm talking about. There is no way we could have implemented a "setTimeout" method in the script engines -- such a method requires detailed knowledge of the internals of IE, and would work in IE and nowhere else. Therefore the sensible place to put it is in IE, not in the language runtime.
  • I am calling a COM object from WSH.  The call is asynchronous and I have to wait for the notification that it has completed.  As I have nothing else to do until I get the data, I go to sleep for a very long time.
    My question is: how should I wake up when I get the data back?  I am used to the paradigm when the interrupt handler stores the data in a buffer and IRETs; the data are processed during normal execution and not in the handler.  Can this paradigm be followed in WSH?  Or is the analogy wrong and the code should follow the pseudo message loop pattern: initialize, sleep, handle events in the meantime, quit explicitly when you are done?  Or is sleeping forever prohibited and I should take naps in a loop?  But then I need a hint how short those naps should be.
  • PingBack from http://www.keyongtech.com/1164738-pausing-execution-of-an-asp

Page 1 of 1 (5 items)