Below is an update to the original CFTHREAD Proof of Concept (POC) that adds experimental multithreading support to CFML on ColdFusion MX 7.0.2 that Adobe Computer Scientist and ColdFusion Engineering Team developer extraordinaire, Rupesh Kumar put together in his own time for you to play with. Our development engineers are called “Scientists” at Adobe which is cool because it means that we understand the importance of experimentation. And like all good scientists, we hypothesize and test – some things make it into the product, others don’t – but we’re always innovating.This POC works with CF 7.0.2 (Standard or Enterprise). While you can do multi-threading and asynchronous CFML with these POC tags, they don’t provide any of the fine-grained threading control you have with ColdFusion Event Gateways and the Asynchronous Gateway, for example. So you don’t get thread pooling, control over how many worker threads can be active or pooled, metering on Gateway messages In/Out, or any of the other advanced capabilities of the Event Gateway architecture on CF7, but they do the basics: run stuff asynchronously in separate threads and allow for the use of local (thread-local) variables, allow access to shared scopes, etc.
A note on the simple example: you'll want to modify both templates to copy a file (I use a “C:\baseline.txt” file) that exists on YOUR system to a directory that exists on YOUR system (I used “C:\____WORKFOLDER”). I’d recommend turning on debugging so you can see the execution times yourself as well (much more dramatic that way). Also note that spawned threads shouldn't count towards Simultaneous Threads slots of the CF Server, so you shouldn't need to adjust that setting to accommodate your extra threading.
The CFTHREAD POC enables you to spawn a new thread and optionally wait for a thread to finish. A thread can be spawned using
This update will be the last for the CFTHREAD POC, but it does address some of thread safety issues of the first CFTHREAD POC, and has the same syntax. The two small additions to this updated POC are that a) you can pass any variable to the thread tag and b) any variables defined in the thread tag are local to the thread.
Each thread has its own local scope and any variable that you define inside the thread goes into that local scope. This is very much like function local scope except that you don’t need to prefix those variables with 'var'. A page scope or other scope variables will be accessible inside the thread using the appropriate prefix like variables.xx or request.xx. CFTHREAD tag also allows passing any variable as attribute to the tag. The attributes thus passed can be accessed using attributes.xxx.
Apart from thread local scope, there is a special scope for thread called "thread" scope. this is a scope in which only the owner thread can write but all other threads can read values from it. This scope can be accessed by "
A thread can put some data in its scope and it can later be retrieved.
Browser Output and Error Handling
CF code written inside CFTHREAD can not write any content to the browser. So any output written using
Similarly, any error thrown from a
1) To start a thread:
This will spawn a new thread and any content between
2) If you want to wait for this thread to finish, you can use
If thread 'th1' is already over by the time you reach here, it will have no effect. Otherwise it will wait for th1 to complete. One important thing about this POC is that you can wait for only user threads that have been created in that request. So you can not use join for any arbitrary thread in the VM, for example. If you only want to do some operation asynchronously and do not need to wait for its completion, you need not use
3) To retrieve a value put in a particular thread scope, simply access that scope variable. So you can use th1.x to get the value of x kept in th1 scope.
4) CFTHREAD does not provide a way to sleep. however if you want to do it, you can use
This code lets the current thread to sleep for 10 secs (10000 milliseconds). For example, if you want 'th1' of above example to sleep for 10 sec, this code snippet will go inside
CFTHREAD POC Setup
The zip file contains two other files
- cfthread.jar - This file should be kept in
- taglib.cftld - This should be kept in
Restart your server and you should be ready to try out the
DOWNLOAD CFTHREAD POC & SAMPLES ( 101K)
Once again, just to be clear, this POC is not a CF product feature at this time, has not been properly QA'd, contains bugs and is unsupported. There is also little chance that should a POC evolve into a feature that the tag syntax will not change (perhaps drastically) in the future, and there are no plans to update the POC as future major versions of CF come out. CFTHREAD may or may not make it into a future release, but that partly depends on feedback from you, our customers.
Enjoy! And thanks Rupesh!
Hopefully Adobe will see this as a successful "experiment" and might start releasing more POC in the future, that based upon their reception by the developers, eventually make their way into ColdFusion.
I personally really hope that CFTHREAD/CFJOIN make their way into Scorpio.
My only thing is I can think of no reason why threads are required in software like ColdFusion; major data manipulation etc should be managed where it came from or at an off peak time - perhaps this is where threading is most usfull by reducing the priority and thus adjusting the timeouts allowed??
I refer this to Brian's post; re the slow running queries example; if queries are slow running (regardless of optimisation) then threading is avoiding the real-time problem and it is time for a application rethink. One slight blip and slow running calls etc will cause the whole thing to fall down - and to then add the complexity of threads?
dunno. Keep it simple I say
There are times when the slow executing processes are out of your control. For example, Verity indexing can be very slow on servers w/a large number of collections.
This is a perfect example of where being able to spawn off a thread to handle the indexing is useful. There's no reason for the user to wait 30 seconds for the content to index. Just spawn a thread and display a message to the user.
Of course I can think of plenty of similar examples where it's useful, this is just one example.
You know it might be abused, of course I think there's a lot of CF functionality that gets abused. It's part of the problem any time you have a programming language that's easy to learn.
You can pretty much take anyone w/a comfort around computers and have them build their first ColdFusion application ("Hello World") within a few minutes. Getting them to really learnd programming is a whole other process--one that takes years.
So well you're probably right saying people will abuse CFTHREAD to just make slow processing code seem fast, they're still going to be in the same boat and still have issues with their servers.
However, in those times when developers do truly understand what's going on and the problem is out of their control, or has been reduced as much as possible, it's going to be very handy.
I definitely see many useful ways of using CFTHREAD. I have a couple month end reports that will be spead up immensley by threading. I have 2 separate long running queries. Right now I have to wait for Query A to finish and then run Query B. With threading I can fire them both of and then use QoQ to join them when they both respond. (These are separate DSN on different servers.)
I think cfthread will probably not be abused as the other examples I gave above, simply because some people just won't get it, no matter how easy it is.
This will helop with some very long running requests I'm trying to fix right now.
Sad to say, but after installing tag "per instruction" I get following error:
You are using tags whose name begins with CF, but the tag is not registered with Neo. Either the tag is not completed yet, or have you been playing with the configuration?
Unknown tag: cfthread. ColdFusion cannot determine how to process the tag cfthread because the tag is unknown and not in any imported tag libraries. The tag name might be misspelled.
Any help is highly appriciated...
Are you sure you updated the correct taglib.cftld and restarted the server? That message sounds like the correct taglib.cftld file wasn't updated. You will also need to recycle the CFMX services for the change to take affect.
Yes. I placed both files to the respective locations and restarted CF server. It didn't work. I installed both files once again and rebooted box. No luck...
If I put code into an include, then thread scope is no longer accessable/exists.
Did I miss something once again...?
You must remember that the whole point of cfthread tag is that the information in the thread is processed asynchronously. That means as blah_blah thread is being processed it's also processing your cfoutput statement. Since the two pieces of code are running simulatenously, there's no way to guarantee the thread is done running.
That's why you need to call the cfjoin tag. To ensure that the core template waits for the thread to complete.
Try calling the cfjoin tag before the cfoutput and see if that doesn't resolve the issue.
I tried to escape this very bad situation by moving cfthread tag into inclides and got following error
Error Occurred While Processing Request
Routines cannot be declared more than once.
The routine "_cffunccfthread_cfping_ACE2ecfm16893343631" has been declared twice in different templates.
I checked value of the cfthread name attribute. Values are definitely different.
Any help is HIGHLY appriciated...