<cfthread action="run" name="a">Will end up with lots of errors in your logs saying things like:
<cfthread action="run" name="b">
Error","cfthread-1","09/24/07","12:03:42",,"A: Thread B cannot be created. Child threads are not supported."
Which is probably not what you actually want, as you would most likely like for you code to actually execute.
I'm not a huge fan of this limitation, but I can kind of understand where the engineers are coming from - they don't want us CF developers to shoot ourselves in the foot with ridiculously spawning multi threaded applications.
So, in my current situation, I wasn't too fussed if I had a whole, brand new thread, but where my code was being run, I was so far down the stack of method calls, I have no way of knowing if the original call had come from a standard ColdFusion thread, or if it had come from a <cfthread> create thread, and both of which were highly possible. However, if the execution wasn't coming from a <cfthread> created thread, I wanted to execute my code inside a <cfthread> statement, as I didn't care what the results where, and it would be faster for the end user just to have the code run asynchronously.
If that just made your head hurt, I basically have a series of method calls that look like:
- makes a <cfthread> call, and calls C()
- Does some work...
- Calls C() from the current thread.
- makes a <cfthread> call, and then does some work
This is an over simplification of the process (mine is far more levels deep), but gives you an idea of the trouble I was facing - the method call could go through A() or through B(), and at the level of C() I wasn't aware of whether or not I had started on the base ColdFusion thread or not.
I could have done this passing a parameter all the way down the method chain to tell it if it should fire asynchronously, but that seemed like a lot of extra work, and would have put a level of complexity within the whole process, and any other process that was related to this, that it didn't seem like the appropriate course of action.
So I thought to myself - there has to be a way to find out if the current thread is a regular, ColdFusion thread, or if it is a <cfthread> invoked thread, and funnily enough, skipping into some Java, there is!
The first thing we have to do, is get access to the java.lang.Thread object:
Thread = createObject("java", "java.lang.Thread");Now, the Thread object, has a great method 'currentThread()', which returns the current thread that the executing code is on:
currentThread = Thread.currentThread();What is good to know, is that Threads in Java can exist in ThreadGroups, which is a handy way of grouping Threads together for common operations, and other clever things. The nice thing here, is that ThreadGroups have a method called 'getName()' which returns the name of the ThreadGroup.
Strangely enough, <cfthread> created threads live inside the ThreadGroup named 'cfthread'! So now we can compare this against the name of the current Thread's ThreadGroup
if(currentThread.getThreadGroup().getName() eq "cfthread")
We can also wrap this up nicely into a quick little UDF:
<cffunction name="amInCFThread" hint="returns 'true' if the current thread is a cfthread, returns false otherwise" access="public"returntype="boolean" output="false">This function returns 'true' if the currently executing code is inside a <cfthread>, and 'false' if it is not.
var Thread = createObject("java","java.lang.Thread");
if(Thread.currentThread().getThreadGroup().getName() eq "cfthread")
So now, in my function C() I can have:
if(amInCFThread())And continue on my merry way!
// run code
// make <cfthread> and run code.
Pretty handy if I'm not sure if my <cfthread>'d code will end up being run by other ColdFusion created threads or not.