Sunday, November 23, 2008    
Home My Books Blog ColdFusion About Me Back    

Calendar
<< May 2007 >>
S M T W T F S
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

Search

Categories
 • Acrobat (2) [RSS]
 • Adobe (71) [RSS]
 • AdobeMAX06 (45) [RSS]
 • AdobeMAX07 (59) [RSS]
 • AdobeMAX08 (46) [RSS]
 • AIR (144) [RSS]
 • Appearances (133) [RSS]
 • Books (69) [RSS]
 • CFEclipse (14) [RSS]
 • ColdFusion (1173) [RSS]
 • Data Services (16) [RSS]
 • Fish Tank (2) [RSS]
 • Flash (108) [RSS]
 • Flex (382) [RSS]
 • Home Automation (3) [RSS]
 • Jobs (100) [RSS]
 • JRun (13) [RSS]
 • Labs (29) [RSS]
 • LiveCycle (23) [RSS]
 • MAX (181) [RSS]
 • Regular Expressions (15) [RSS]
 • RIA (12) [RSS]
 • SQL (38) [RSS]
 • Stuff (505) [RSS]
 • Tips (CF Studio) (80) [RSS]
 • Tips (CF) (795) [RSS]
 • Tips (Dreamweaver) (91) [RSS]
 • Tips (Flex Builder) (2) [RSS]
 • Using CF (140) [RSS]
 • Wireless (100) [RSS]

Other BLOGs
 • Charlie Arehart
 • Lee Brimelow
 • Ray Camden
 • Christophe Coenraets
 • Sean Corfield
 • Mihai Corlan
 • Cornel Creanga
 • John Dowdell
 • Danny Dura
 • Enrique Duvos
 • Steven Erat
 • Kevin Hoyt
 • Serge Jespers
 • Adam Lehman
 • Duane Nickull
 • Miti Pricope
 • Andrew Shorten
 • Ryan Stewart
 • James Ward
 • Greg Wilson
 • Full As A Goog

RSS Feeds
 • Feed
 • Subscribe

Join my mailing list and find out about new books and other topics of interest.

Thoughts, ideas, tips, musings, and pontifications (not necessarily in that order) by Ben Forta ...
NOTE: This is my personal blog, and the opinions and statements voiced here are my own.

Viewing By Entry / Main
May 21, 2007

Multi-Threaded Application Development In Scorpio

ColdFusion MX7 introduced the ability to asynchronously spawn ColdFusion requests using an event gateway. While many take advantage of this capability, it has some significant limitations, the biggest of which is that threads can only be spawned, there is no way to monitor spawned threads or wait for them to finish. (The other limitation is that the functionality is only available in ColdFusion Enterprise).

ColdFusion Scorpio provides far more sophisticated multi-threading capabilities via the new <CFTHREAD> tag. This tag is used to perform several actions:

  • JOIN causes the current thread to wait until one or more specified threads have finished processing.
  • RUN creates a new thread which starts processing immediately.
  • SLEEP makes another thread pause for a specified number of milliseconds.
  • TERMINATE kills another thread.

There are lots of use cases for this new functionality, but at a minimum there are two primary usage scenarios:

  • Many requests process user submissions, for example, a user uploaded file. The way most ColdFusion applications work today is that the file is processed on the server (parsing it, converting it, saving it, etc.) while the user waits. But in truth, there is no reason users should have to wait for your application to finish its processing. A better user experience would be to receive the file in the action page, spawn a new thread to actually process it, and return control back to the user instantly. This creates a far more responsive user experience.
  • Applications often have to perform multiple operations (perhaps updating database rows, writing log entries, generating an e-mail, firing server-side HTTP requests, and more). Most ColdFusion applications perform these tasks sequentially, one after the other, and then returning to the user when complete. But if the various operations are not actually dependent on each other, you could spawn a thread for each, having them execute concurrently, and if necessary waiting until they are complete to continue processing. The result is a faster application, as multiple operations are being performed concurrently.

The code to spawn a thread is very simple:

<!--- Use a separate thread to perform file processing --->
<cfthread action="run" name="threadFile" file="#myFile#">
   <cffile file="#ATTRIBUTES.file#" ...>
</cfthread>

Here a thread named 'threadFile' is spawned. An argument (the file to be processed) is passed to <CFTHREAD>, and so that attribute is available within the thread in the ATTRIBUTES scope.

Within threads there are several important scopes. Any locally defined variables are implicitly thread local. THREAD is a special scope (a sub-scope of VARIABLES) that is available to all threads spawned by a single parent. ATTRIBUTES is used to access any variables passed as attributes to <CFTHREAD>.

The previous example spawns a thread that could continue processing long after the parent page terminates. If you needed to wait for a thread to complete you could use the following code:

<cfthread action="join" name="threadFile">

JOIN is used to wait for one or more threads to complete, and multiple thread names may be specified (as may a timeout value).

Once defined, the thread name can be accessed as a structure which exposes the following members:

  • ELPASEDTIME is the amount of time since the thread was spawned.
  • ERROR contains any error messages generated by the code in the spawned thread.
  • NAME is the thread name.
  • OUTPUT contains any generated output. This output will not be sent to the client, but parent page code can access the output which can then be used as needed.
  • PRIORITY is the thread priority level (HIGH, LOW, NORMAL).
  • STARTIME is the time the thread started.
  • STATUS is the thread status (NOT_STARTED, RUNNING, TERMINATED, COMPLETED, WAITING).

So, to check that threads executed properly without errors, you could JOIN the threads, and then check STATUS to see if they completed. A status of TERMINATED means an error occurred (or that threads were explicitly terminated) in which case ERROR would provide details as to what happened.

TrackBacks
There are no trackbacks for this entry.

No trackback URL. Trackbacks are only allowed via interactive form.

Comments
holy threadtastics! ben keep the good news coming broseph!
# Posted By tony of the weeg clan | 5/21/07 3:52 PM
I'm trying to see how cfthread can help one of my apps which can take 2 to 10 secs to process some pages - lots of db transactions, log writing, web services, etc, all in one page request. While some tasks can be spawned off as separate threads (others must be done sequentially) what is there to gain using cfthread if CF has to report back to the user to say if everything went well or not? The user will still have to wait for the processes to complete. On a busy site wouldn't creating more threads take a share of cpu resource and effectively slow down other user's requests?

Other options, keeping usability in mind, are using CFFLUSH to inform users about how their request is coming along, or using Ajax to submit the request you can let users carry on immediately and update them on their request via a pop-up or status panel on the page. Thoughts?
# Posted By Gary Fenton | 5/21/07 5:32 PM
Where are the CF8 docs?
# Posted By Mark Ireland | 5/21/07 7:42 PM
Is this going to be an enterprise only function like the event gateways in CF7, or will this be available for both versions?
# Posted By Mike | 5/21/07 8:33 PM
Ben,
Could this be used to thread off a 'report generation' show a Report is being compiled page with a poll to check if the thread has completed (bad example).

In other words is the thread name only available in the variables scope (in effect isn't accessible once a request is complete).

Adam
# Posted By Adam Reynolds | 5/22/07 4:26 AM
Gary:
The question to ask is whether the user NEEDS to be informed, in "real time" that the process ran correctly. Sometimes this is essential, sometimes this is just because it kinda made sense to have something at the bottom of the template popping up an alert saying "yep, all good" after the process. I think often the latter approach isn't really necessary: surely the assumption on a robust system should automatically be that it worked OK?

I think in a lot of situations the user (or not even that specific user, but an admin user) can simply be notified in exceptional circumstances. This can be effected by raising events when something goes wrong, and having a handler which takes an appropriate action (writing to a log; sending an email; interrupting the UI (either of the user initiating the task, or an admin user); [whatever]).

--
Adam
# Posted By Adam Cameron | 5/22/07 5:55 AM
Gary, as Adam C wrote, it's going to depend on the application. If you need while-you-wait processing, then don't use threads. If not, then you can.

Mark, when CF8 is public so will be the docs.

Mike, versioning and editioning are not final or announced yet.

Adam R, absolutley. Or you could e-mail it to the user when done. Or display an alert on the next page the user displays (maybe the thread updates a flag in th users SESSION scope which is checked in an include used on each page). Or send am IM alert. ... Lots of options.

--- Ben
# Posted By Ben Forta | 5/22/07 7:47 AM
Ben -

This might be a silly question, but I presume that this <cfthread> tag will allow the 'initial' thread to be completed, so that another user can use the 5-8 thread?
# Posted By Patrick Whittingham | 5/22/07 10:16 AM
Man I could make use of this. Lately I've been experimenting with writing stock market prediction software, my scripts often take upwards of 30-40 minutes to process.

I'm still not sure i see how this syntax works. Is the #attributes.file# the .cfm file that's running? What if the file is a CFC?
# Posted By Steve Nelson | 5/22/07 1:03 PM
Patrick, sure, if the spawned thread is still running, and the parent finishes, then that parent thread is freed up for other requests.

Steve, you'd prob just do a <cfinvoke> or CreateObject() withijn the <cfthread> passing whatever you want on to it.

--- Ben
# Posted By Ben Forta | 5/22/07 2:07 PM
Oh baby! That's sweet!
# Posted By Steve Nelson | 5/22/07 3:39 PM
Ben -

Thanks Ben. Since one might have lots of 'children' spawned threads, will CF 8 allow one to monitor these threads so to test the 'application' is scalable with alot more requests (end-users). It would be great to emulate 'x' number of users since these threads could be either/both 'database/web service' threads or OS threads <cffile>. I think this tag will be great if one can 'effectively' use it properly.

Pat
# Posted By Patrick Whittingham | 5/22/07 4:07 PM
Pat, yes, the server monitor will let you monitor threads. Also, if you spawn more threads that CF will support, then they will just queue up like any other CF requests.

--- Ben
# Posted By Ben Forta | 5/22/07 4:36 PM
Will the server's request timeout apply to threads? For instance, if a normal cfm page times out after 30 seconds, would the thread processing also time out after 30 seconds? This is very cool functionality, thanks for sharing.
# Posted By Eric | 5/22/07 5:00 PM
Eric, I believe so. Unless you use a processing directive to change that, just liek any other request.

--- Ben
# Posted By Ben Forta | 5/22/07 6:15 PM
Is optional to insert a cfthred join after a cfthred?
If a create a page (like a scheduled page) with some thread parallel processes, do I need to close page with a cfthread join of all opened threads?

I've some problem with a sms scheduler. Sometimes sending don't need. And sending mail too.
Thanks

p.s.: if you want I created an alternative to captcha, if you want you may contact me via mail, I don't want spam here :)
# Posted By Merlinox | 4/28/08 6:26 PM
Is there a way for us guys using cfthread with cf8 standard (and dont have the monitoring capability) to show a list of outstanding threads queued up and know when they are all caught up? I have an app that runs on a schedule and does some work in the background, cfthread is perfect, but it would be nice to know what the queue looked like at any given point.
# Posted By Anthony Webb | 7/13/08 10:52 PM

  © Copyright 1997-2008 Ben Forta, All Rights Reserved