我有一个应用程序,每晚发送几个100k的电子邮件,所以为了加快处理速度,添加了一些cfthread。
这导致了一些奇怪的错误,我发现在一个线程中创建的变量正在被另一个线程修改。从我读过的文档来看,在一个线程中创建的变量应该只对该线程可见?
做了一个简单的测试,如下所示:
<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,正如我所期望的那样。
有人知道这是怎么回事吗?
发布于 2012-11-13 04:01:52
我相信你运行cfthread的目的是错误的。看起来线程2中的tmpEmailBody依赖于thread1。您不应该在单独的线程中运行依赖代码。
与邮件相关的cfthread更好的用法可能是
Thread1 {从a-m列表中选择以a-m开头的数据库中的电子邮件}
线程2{从数据库中选择电子邮件,其中电子邮件从n-z开始}从你的列表中选择n-z}
你的两个线程同时运行。这两个查询可以同时进行,但你不能在一个线程中保存变量,并希望它能在另一个线程中匹配你的调用时间。
发布于 2012-11-13 06:58:32
变量tmpEmailBody是在Variables作用域中创建的,而不是在限于线程的作用域中创建的。线程将以随机顺序和随机时间执行,因此导致错误的原因是,在thread2执行其第一行之前,thread1尚未执行其最后一行。
在使用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>https://stackoverflow.com/questions/13348767
复制相似问题