Contents |
NOTE: CFTHREAD and multi-threaded CFML programming were originally introduced in BlueDragon, but the later implementation by Adobe introduced in ColdFusion 8 differed from BlueDragon's implementation. Open BlueDragon now supports the ColdFusion 8 API for multi-threaded programming. What is outlined here is the original implementation of CFTHREAD, which is still supported in Open BlueDragon.
CFTHREAD is used to support multi-threaded programming in CFML. CFTHREAD spawns a new thread and supports additional functionality related to multi-threaded programming.
<cfthread name="name of thread"
output="boolean"
attributecollection="struct containing values for the attribute scope">
| Attribute | Req/Opt | Default | Description |
|---|---|---|---|
| name | optional | N/A | The name of the thread. Required if CFJOIN is to be used with the thread. |
| output | optional | N/A | Boolean indicating whether or not the output generated in the CFTHREAD body should be stored. If output is true, a GENERATEDCONTENT variable is added to the thread variable. The output attribute is ignored if the name attribute is not provided. |
| attributecollection | optional | N/A | A CFML structure containing the values for the attributes scope of the CFTHREAD tag body. Variables may also be passed into the attributes scope as explicitly declared attributes of the CFTHREAD tag. |
CFTHREAD spawns a new thread, meaning code within the CFTHREAD body is executed asynchronously, i.e., in parallel with other code being executed. Specifically, when a CFTHREAD tag is encountered, a new thread is created to execute the body of the CFTHREAD tag, and execution of the current thread continues processing the code immediately following the close CFTHREAD tag.
The body of the CFTHREAD tag does not have access to the variables scope of the page or CFC containing the CFTHREAD tag. Like a custom tag, CFTHREAD has its own separate variables scope, but unlike a custom tag, the body of CFTHREAD does not contain a caller scope.
Code within the CFTHREAD body can invoke functions that are declared on the page on which CFTHREAD is executing. If CFTHREAD is used within a CFC function or the pseudo-constructor area, the CFTHREAD body has access to the CFC's THIS scope and may invoke any function defined in the CFC.
CFTHREAD tag attributes are available via the attributes scope within the CFTHREAD tag body. Using the ATTRIBUTECOLLECTION attribute of the CFTHREAD tag you may specify a struct containing attributes that will be available inside the CFTHREAD body.
CFTHREAD has access to the Application and Server scopes. CFTHREAD does not have access to the following scopes:
If variables from these scopes are needed within the CFTHREAD body, they must be passed in via the ATTRIBUTECOLLECTION.
Note that attributes may also be passed into the CFTHREAD body as attributes of the CFTHREAD tag itself. For example, the following code would make an attribute of customerID available in the attributes scope of the CFTHREAD body:
<cfthread name="myThread" customerID="1"> <!--- cfthread body here ---> </cfthread>
For additional information on CFTHREAD functionality, please see CFJOIN, CFPAUSE, and CFINTERRUPT.
Spawn a new thread to send an email to the email address specified in the email attribute of the CFTHREAD tag:
<cfthread email="customer@somewhere.com">
<cfmail from="sales@company.com" to="#attributes.email#" subject="Greetings!">
<!--- email content here --->
</cfmail>
</cfthread>
Spawn a new thread named "myQueryThread" to run a query, and pass in the datasource name and customer ID from scopes not accessible by CFTHREAD using ATTRIBUTECOLLECTION:
<cfset attribs = StructNew() />
<cfset attribs.dsn = Application.DSN />
<cfset attribs.customerID = Session.customerID />
<cfthread name="myQueryThread" attributecollection="#attribs#">
<cfquery name="myQuery" datasource="#attributes.dsn#">
SELECT *
FROM customers
WHERE customer_id = <cfqueryparam value="#attributes.customerID#" cfsqltype="cf_sql_integer" />
</cfquery>
</cfthread>
In order to wait for a thread to finish you use the JOIN action, as in:
<cfthread action="join" name="myThread" />
You can also set variables or use the output of a cfthread after the thread has been created:
To set a variable:
<cfthread name="myThread" attributecollection="#attribs#"> <some code> <cfset thread.myoutput = somevariable> </cfthread> #thread.myoutput#
The other option is to use a output of the cfthread with:
<cfthread name="myThread" attributecollection="#attribs#" output="yes"> <some code> <cfoutput>#somevariable#</cfoutput> </cfthread> #cfthread["myThread"].output#