ProgID-s
and ClassID, Members reference
Overview
The COMScriptThread object like COMThread object allows the
application to execute separate threads. Unlike COMThread the
COMScriptThread is especially designed to run scripts in separate
threads. This makes it much easier to use and leaves place for
features that allow full compatibility of the code that depends on
it with all the supported platforms. For example with COMThread
object you need a COMApartment object in order to run script in a
separate thread, but on Windows CE based devices COM system does
not support single threaded apartments which makes COMThread not
applicable for scripts and many other COM objects on these devices. COMScriptThread does not
have these set backs, but of course there is a price - much
thinner communication with the thread, applicable for scripts
only, strictly defined data exchange technique.
Therefore the COMScriptThread object is best for all the
scenarios where it will do the job. Also it requires very little
learning efforts, no deep COM knowledge and thus can be used by
any developer.
How it works - lifecycle
The COMScriptThread object itself is the thread controller and
also holds a data dictionary/collection object accessible for the
both sides - the application that creates the thread and the
script running in the thread.
The scheme above illustrates the life cycle of the
COMScriptThread object. Note that in case of ASP application, for
example, everything displayed there may happen in different pages
and during the processing of different requests. For example the
application may keep the object in the Application (or Session)
and perform actions in different ASP pages of the applications.
And this is the main purpose of this component. The wait actions
are optional, but are in fact needed in almost any situation as
the application cannot be sure that the last operation is
completed. In fact the Wait method and the Busy
property implement almost the same functionality, but Wait method
waits the specified timeout period the thread to complete whatever
it is doing, while Busy returns immediately indicating if the
thread is currently busy.
Now about the life cycle as whole. As you can see there are two
general ways to use the thread:
- All the work you need to implement can be in the global part
of the script and it is executed linearly (in a way very
similar to the Windows Script Host scripts or ASP pages). In
this case the thread is Started then the application
can wait/check for the completion whenever it needs the
results from the code running in the thread.
- The other way to use the thread is to Start it and
then when it initializes to Execute one or more
routines implemented in the thread's script one or more times.
This can be performed multiple times.
If you don't know this yet - the Active Scripts can be used in
several different ways. They can be executed sequentially, or
started and then placed in stand-by mode and then the routines
implemented in them can be called in a way very similar to the way
you call methods of a COM object or they can be attached as event
sinks to certain event sources. This object allows the first two
techniques to be used with the thread's script. However, note that
only routines without parameters can be executed (with the Execute
method). This is not a problem as the routine can fetch parameters
from the Context collection (See Value default property and the
Context namespace).
So, the object starts the thread when the Start method is
called and stops it when the Stop method is called. If the
thread's script is written to perform its tasks when it is started
then the application sticks to the first usage technique and it
should wait/check for the completion when it needs the result,
then it should stop and release the COMScriptThread object or just
stop it if the object will be reused. If the application intends
to use the second technique then the script should be written to
initialize (perform some global initialization/preparation tasks)
and the real task(s) should be implemented as routines in it (they
can do quite different things) and then the application can
execute these routines asynchronously in the thread (i.e. the
Execute schedules the routine execution and returns, then the
thread performs it).
The script in the thread
The script in the thread is written as plain script (plain
script text). It has certain namespaces supplied by the
COMScriptThread object:
Context - The script can access the same
collection/dictionary object that is accessible for the outer
application through the Value property. For details see the Value
property.
Creator - This namespace is available only if the AddCreator
property is True before the script is started (which is
default). It is a Pack1Creator
object. Through it the script can create COM objects, composite
objects and so on. It offers better performance when the
script creates other objects from the ActiveX pack1 library and
also creates them in the same thread.
So the communication between the application and the thread's
script is done through the Context collection. The
application that creates the thread refers to it through the Value
property and the script in the thread through the Context
namespace. For example the outer application can do the following
to pass a parameter:
o.Value("UserName") = "Joe"
o("DB") = "C:\db.ndb"
Because the Value is a default property it can be omitted.
Now the script in the thread can read these values:
Dim userName, dbFile
userName = Context("UserName")
dbFile = Context("DB")
Of course, you should ensure that the values are set before
the thread refers to them. For example before it has been
started or before the routine that needs them has been
executed.
The reverse operation can be performed too - e.g. the
thread's script can set certain values and then the application
is able to read them.
The Context collection can be referred at any time, therefore
certain values can be used for additional synchronization, for
example to indicate progress, intermediate results etc.
Usage
You can see a simple example on the COM
threads objects page. In general the script threads are needed
when you need to perform time consuming tasks preserving the
application ability to respond to the user while the operation is
in progress. In Windows Scripting Host (WSH) or Micro Script Host
(supplied with ActiveX Pack1 library) the application is usually
one script executed sequentially. In this case it may start a
thread do some other work and then check/wait for the thread
completion when the results from it are needed. In this case you
will not need to keep a reference to the COMScriptThread object
anywhere else - a variable in the script will do. In Active Server
Pages application the application usually consist of more than one
pages/scripts executed when the user requests them. The ASP
environment offers places where these scripts/pages may save
values and objects and preserve them between the separate pages
execution - the Application and Session. Thus in case of ASP
application the page that creates the COMScriptThread object may
save it in the Application or Session, then another page (or the
same page) can start the thread, then another page can check/wait
for the thread operation to complete and get the results from the
Context collection using the Value property.
Recommendations: In multi-user applications (such as ASP
applications) you should be aware of the number of the threads you
are running. The application should limit their number - for
example for a server application they should be limited according
to the memory and CPU resources, in ALP applications their number
should be limited as much as possible because you cannot be sure
on what kind of machine the application will run. If needed you
can easily implement a thread pool and use the first free thread
object to execute the new task in it or inform the user that the
threads are too much at this moment and he/she should
request the operation later. You can also offer configuration
features that allow the number of the thread in pool to be
configured etc. Of course the actual way you manage the threads is
up to you - some applications may prefer to keep on or more
threads initialized and execute routines in their scripts, others
will prefer to start threads whenever they need asynchronous
operations. The way you choose depends on the work you are doing.
For example if there are several different tasks that use similar
or the same data, work over one single DB and have something in
common in general - then implementing them as routines in one
single script and then executing them as needed will produce more
compact and effective code then implementing them in separate
script files. On contrary if the tasks are too different and over
different data and resources, sometimes they could be even fetched
from an user specified location - then implementing them as plain
sequential scripts will give you better results.
The object will uninitialize, stop the thread when released
(e.g. Set o = Nothing if the o is the only variable that holds the
object), but note that the work the script does may differ and
sometimes may concern resources that need to be properly
obtained/released. So, it is recommended to take care to perform
proper uninitialization especially if the second technique is used
(executing routines) before stopping and releasing the thread, for
example by implementing a routine that uninitializes the resources
and executing it before stopping/releasing the thread.
About the threading models: By default the object uses
multi-threaded COM apartments. Even if the script uses apartment
threaded objects to do its work this will not be a problem in
almost all the imaginable scenarios. However if because of certain
reasons you need to initialize the thread as single-threaded
consider the fact that this will not work on Windows CE devices.
|
Name |
Description |
|
Start |
Starts the thread with the
given script |
|
Execute |
If the thread is started
and in stand-by executes the given routine from the loaded
script. |
|
Stop |
Stops the thread. |
|
Wait |
Waits for the thread to
complete the current operation. |
|
Value |
Default property: Holds a
VarDictionary based collection (dictionary) that is
accessible for the both - the application creating the
thread and the script in the thread. |
|
Busy |
Boolean: indicates if the
thread is busy. |
|
AddCreator |
Boolean: If set the running
script in the thread will have a Pack1Creator object
accessible through the Creator namespace. |
|
LastError |
String: Contains the last
error |
|
MultiThreaded |
Boolean: If set (default)
the thread will be initialized as multithreaded COM
apartment. |
|
Priority |
Integer: The thread
priority |
|
Result |
Variant: The result of the
last routine execution (meaningful if the routine is a
function) |
|
Success |
Boolean: Indicates if the
last operation was successful (routine execution, thread
start) |
|
Timeout |
Positive integer: Timeout
for the internal wait operations. |
|
Active |
Indicates if the thread is
active (Busy or stand by) |
|