CFTHREAD中的范围问题

时间:2012-11-12 17:49:22

标签: multithreading coldfusion scope cfthread

我有一个应用程序,每晚发送几十个电子邮件,所以为了加快处理添加了一些cfthreads。

这导致了一些奇怪的错误,我发现在一个线程中创建的变量正被另一个线程修改。从我读过的文档中,在一个线程中创建的变量应仅对该线程可见?

做了一个简单的测试:

<cfthread
    name="thread1"
    action="run">

    <cfsavecontent variable="local.template_body">
        <cfinclude template="templates\6\2\bulletin_template.cfm">
    </cfsavecontent>

    <cfset tmpEmailBody = template_body>
</cfthread>

<cfthread
    name="thread2"
    action="run">

    <cffile action="append"
            file="C:\inetpub\error1.txt"
            output="#tmpEmailBody#">        
</cfthread>

“tmpEmailBody”的内容已成功写入文件。

奇怪的是,如果我删除cfsavecontent部分,并具有: <cfset tmpEmailBody = "test">,然后第二个线程引发错误,tmpEmailBody没有被定义,正如我所期望的那样。

任何人都知道这里发生了什么?

2 个答案:

答案 0 :(得分:0)

我相信你的cfthread运行错误的目的。似乎线程2中的tmpEmailBody依赖于thread1。您不应该在单独的线程中运行相关代码..

与邮件有关的更好地使用cfthread可能是

Thread1 { 从数据库中选择电子邮件,其中电子邮件从a-m开始  出你的a-m列表 }

线程2 { 从电子邮件从n-z开始的数据库中选择电子邮件}  你的名单n-z }

两个线程同时运行。这两个查询可以同时进行,但你不能将变量保存在一个线程中,并希望它与另一个线程中的调用时间匹配。

答案 1 :(得分:0)

变量tmpEmailBody正在Variables范围内创建,而不是在仅限于该线程的范围内。线程将以随机顺序和随机时间执行,因此导致错误,因为thread1thread2执行其第一行之前未执行其最后一行。

使用cfthread时,所有正常范围都不是线程安全的(而不是对ColdFusion请求线程的线程安全;也就是页面线程)如果要确保在一个线程中创建/使用的变量与所有线程隔离其他线程则必须使用线程范围。这在ColdFusion文档中正式记录为Using thread data

我猜想你在两个线程之外声明tmpEmailBody,但是因为将cfset更改为静态字符串会给出预期的行为,我会说cfsavecontent存在“问题”,它写入Variables范围而不是线程局部范围,该范围应归档为another scoping gotcha

由于ColdFusion文档示例有一些不足之处,我将重写您的代码,就像您想要将电子邮件正文从一个线程传递到另一个线程一样。您已经说过这不是您的预期用途,但会显示各种线程范围。以下代码在不需要时将值复制到不同的范围中,但希望能够使不同的范围更清晰。并且,正如其他人所说,下面的任务是线程使用不当。

<cfthread
    name="thread1"
    action="run">

    <cfset var template_body = "">

    <cfsavecontent variable="template_body">
        <cfinclude template="templates\6\2\bulletin_template.cfm">
    </cfsavecontent>

    <cfset thread.tmpEmailBody = template_body>
</cfthread>

<cfthread action="join" name="thread1" timeout="60">

<cfset Variables.tmpEmailBody = cfthread["thread1"]tmpEmailBody>

<cfthread
    name="thread2"
    action="run"
    emailBody="#Variables.tmpEmailBody#">

    <cffile action="append"
            file="C:\inetpub\error1.txt"
            output="#Attributes.emailBody#">        
</cfthread>