Advanced COM COMApartment object
ProgID-s and ClassID 

Members reference 

COMApartment object implements a thread with initialized COM in it. By default single-threaded COM is initialized, through the Pack1Creator object a multi-threaded apartment thread can be created also (for advanced usage only).

Usually the script and the components created by it are created in the same apartment where the script runs. As the apartments are related to the threads the only safe and always guaranteed way to run an object's method or another script in a separate thread is to create it in a COM apartment independent of the apartment where the main script runs. So one of the main purposes of the COMApartment object is to support the COMThread object. To illustrate this lets review this example:

Example

We have a script we want to run in a separate thread. Lets put it in a file called thread.js (JScript):

var Result = "";
function isSimple(n) {
    var j;
    for (j = 2; j <= n/2; j++) {
        if ((n % j) == 0) return false;
    }
    return true;
}
for (i = 0; i < 40000; i++) {
    if (isSimple(i)) {
        Result += String(i) + " ";
        State("Cur") = i + " of 40000";
    }
}

This code calculates the simple numbers in the range from 1 to 40000. This will take considerable time and we want to start this task in one ASP page and then check how it goes from time to time by using another page. Start task page will contain code like this (VBScript):

Set ap = Server.CreateObject("newObjects.utilctls.COMApartment")
Set host = ap.Creator.CreateObject("newObjects.Scphost.ScpMan2")
Set sf = Server.CreateObject("newObjects.utilctls.SFMain")
Set file = sf.OpenFile(Server.MapPath("thread.js"),&H40)
ap.Priority = -15
b = host.LoadEngine("JScript")
If Not b Then Response.Write "FAILED to load the engine<BR>"
b = host.AddText(file.ReadText(-2))
If Not b Then Response.Write "FAILED to load the script<BR>"
host.Add "State", Application
Set Application("Host") = host
Set Application("Ap") = ap
Set thread = Server.CreateObject("newObjects.utilctls.COMThread")
Set Application("Thread") = thread
thread.Activate
thread.Execute host, "Run"
Response.Write "Thread started<BR>"
Response.Write "Thread busy indication: " & thread.Busy & "<BR>"
Set thread = Nothing

In the code above we create a COMApartment object and we are using the Pack1Creator object created automatically in it (obtaining it from the Creator property). As this object is created in the apartment any object created by it (unless the created object is not registered as free-threaded) will be created in the same COM apartment. The COMThread object internally creates another apartment and calls from it our script host component in the first apartment. Thus the both are fully independent from the ASP page and the specifics of the ASP engine (IIS or ALP) will not interfere.

To allow communication with the ASP pages we pass the Application object to the script that will run in the thread. As the Application object is independent from the current page it can be accessed directly from the script in the thread and from the page. The thread check page will have code like this:

Set thread = Application("Thread")
If thread.Busy Then
   Response.Write "Thread still busy<BR>"
   Response.Write "Progress: " & Application("Cur") & "<BR>"
Else
    %>
        <H4>Complete</H4>
        <P><%= Application("Host").script.Result %></P>
     <%
End If 

It only checks the Application value where the progress is reported (the "Cur" variable) and also checks if the thread is still busy executing the script. If it is busy the progress is reported, if the task is complete the result from the script is extracted.

Notes about the sample:

As it can be seen above the execution of the script is done by creating a ScriptManager2 component, loading the script from the file in it and forcing the COMThread object to run it. The statement:

thread.Execute host, "Run"

actually means "execute method Run on the object host". The method executed may not have arguments. As the method is called from the separate thread maintained by the COMThread object the ASP page execution will continue while the other script is starting too.

The priority may puzzle you. We want to set lower priority to the thread but instead we set the priority for the COMApartment and not for the thread - why? (see COM Apartments and threads) The call is initiated in the thread maintained by the COMThread but it is actually executed in the thread maintained by the COMApartment object because of the COM synchronization mechanisms. So we tune the execution by tuning the apartment and not the initiator thread!

This will be different if we execute free-threaded object's method but scripts must be created in single-threaded apartments because they must be called from the thread in which they are created.

Members reference

Name Description
Creator Returns the Pack1Creator object for the apartment
Destroy Destroys the apartment immediately.
MultiThreaded Returns a Boolean value that indicates if the apartment is Multi-threaded
Priority Gets/Sets the priority of the thread apartment
newObjects Copyright 2001-2006 newObjects [ ]