2

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!

  • 3
    You're not showing us enough of your code. it's the `lots of actions` bit that' going wrong, but you don't show us it. There's no need to show us the actions that are working fine, but you kinda need to show us the big that's *not* working right! – Adam Cameron Dec 04 '15 at 14:41
  • Few noteworthy things. First of all there is no `index` attribute in `cfthread`. Second, while joining threads you need to pass list of threads to be joined under `name` attribute. – Pankaj Dec 04 '15 at 15:04
  • I thought my edit comments would show here. I've fleshed out the middle bit really to show where the index is used. I've tried using the list of threads in the join, but that didn't help. This is the first time I've tried using cfthread, so I freely admit to not having a great understanding of it! –  Dec 04 '15 at 15:07
  • Please elaborate on `What ends up happening is that every loop iteration repeats the last value in the list`. – Dan Bracuk Dec 04 '15 at 15:24
  • Say I have this list of IDs: 24, 44, 68, 88, 91, 95, 99. When the final output is shown, I have 7 records, but they're all of ID 99. It seems the thread join only joins the last loop to itself. –  Dec 04 '15 at 15:29
  • @Pankaj you can pass in any variables you want through the `cfthread` attributes, which is what he's doing with the `index` attribute. He just wasn't referencing it correctly in the thread. They are stored in the `ATTRIBUTES` scope in each thread. In his case, he should've used `ATTRIBUTES.index` inside the thread instead of just `x`. – beloitdavisja Dec 04 '15 at 16:07

1 Answers1

1

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?

Mark A Kruger
  • 7,183
  • 20
  • 21
  • That link got me looking in the right place. I was making the mistake of using the index from the loop as my variable in the queries. When I changed it to use thread.name, I got the unique IDs the cfthread was tracking, and now it works fine. Thanks! –  Dec 04 '15 at 15:35