coldfusioncfloopcfthread

Using cfthread inside cfloop results in random output


I have a routine in ColdFusion that loops over a list of application IDs. Inside that list, many things happen, including the generation and merging of PDF docs. This gets very slow so I took a look at what cfthread can do for me. The results are promising; a 40 second run time is reduced to 4 seconds.

However, cfthread, as is its nature, has no idea of what the loop is doing. Here's a code sample.

<cfloop list="#form.User_Id#" index="x">
    <cfthread name="thread#x#" action="run" index="#x#">
          <cfdocument format="PDF" name="report" filename="#fileToDownload#" overwrite="yes">
          <cfdocumentsection>
          <cfquery name="example" datasource="DS">
             SELECT * FROM Table
             WHERE ID = #x#
          </cfquery>

          <cfoutput query="example">
               All the output
          </cfoutput>
          </cfdocumentsection>
    </cfthread>
</cfloop>

<cfthread action="join" />

What ends up happening is that every loop iteration repeats the last value in the list. So what on earth do I need to do to make this work?

Thanks!


Solution

  • Probably need a bit more as Adam said.

    If there is an "end result" you are looking for here, where your "final PDF" is dependent on the work being done by the loop/thread code, the the code above is going to give you inconsistent & unpredictable results.

    Also note that the code above has the potential to create an arbitrary number of threads based on the length of your list. It will create these threads - as you have noted - as "fire and forget" - letting them do their thing simultaneously. What you need to do is figure out A) how many threads you need or your system can handle and then B) devise your looping so that you terminate or join your threads appropriately. That way they are a part of THIS request and not just sort of arbitrary pieces of work tooling away after the main request is done.

    Ray (Camden) has a good example of this on his blog where he loops 10 times then joins them ALL together. That may not be feasible if your code runs often or simultaneously (you could overrun your thread request limits) but might be the right approach for a scheduled task. Here's the link to Ray's article.

    http://www.raymondcamden.com/2009/05/18/CFTHREAD-When-to-join

    You could think in discreet "chunks" of work that makes your thread choices predictable. For example, in your loop you could create up to 5 threads and then join them on the 5th iteration, the 6 iteration would start the next grouping... see what I mean?