2012-11-12 52 views
1

我有一个应用程序每晚发送几封100k的电子邮件,所以为了加快处理速度,增加了一些cfthreads。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心不是定义,如我期望的那样。

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

回答

0

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

更好地利用cfthread的一切有关的邮件可能是

线程1 {从数据库 选择电子邮件,其中电子邮件从开始我 出你的列表是 }

线程2 {从数据库 选择电子邮件,其中电子邮件,从新西兰开始} 您的列表NZ }

你的线程都在运行第同一时间。这两个查询可以同时进行,但是不能将变量保存在一个线程中,并希望它能够在另一个线程中匹配您的呼叫时间。

+0

该代码只是为了演示似乎违背Coldfusion文档的行为。我的实际应用与您所说的相似,我实际上希望我的两个线程中的变量彼此完全隔离 – Omiron

0

变量tmpEmailBody正在Variables范围内创建,而不在限于该线程的范围内。线程将以随机顺序和随机时间执行,因此错误是由于thread1尚未执行其最后一行,因此thread2执行其第一行。

使用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> 
+0

在您给Coldfusion文档的链接中,它指出“线程局部范围是一个隐含范围,包含只在线程中可用的变量,并且只存在于线程的生命周期中。在cfthread标签体内定义的任何变量(未指定作用域名称前缀)位于线程本地作用域中,并且不能被其他线程访问或修改“。所以这看起来好像可能是一个coldfusion bug/gotcha – Omiron

+0

我认为这个问题是复杂的,因为你的线程存在于函数内部。 'local'范围是基于函数的,因此不能是线程本地的。如果从'cfcontent'中删除'local.',会发生什么? – nosilleg