【问题标题】:Scope issue in CFTHREADCFTHREAD 中的范围问题
【发布时间】:2012-11-13 06:58:31
【问题描述】:

我有一个应用程序,每晚发送几十万封电子邮件,因此为了加快处理速度,添加了一些 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 部分,并且有: &lt;cfset tmpEmailBody = "test"&gt;,然后第二个线程引发错误,tmpEmailBody 没有定义,正如我所料。

有人知道这里发生了什么吗?

【问题讨论】:

    标签: multithreading coldfusion scope cfthread


    【解决方案1】:

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

    在邮件方面更好地使用 cfthread 可能是

    线程1 { 从电子邮件从 a-m 开始的数据库中选择电子邮件 列出你的 a-m }

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

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

    【讨论】:

    • 该代码只是为了演示似乎违反冷融合文档的行为。我的实际应用程序与您所说的类似,我实际上希望我的两个线程中的变量彼此完全隔离
    【解决方案2】:

    变量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>
    

    【讨论】:

    • 在您提供给coldfusion文档的链接中,它声明“线程局部范围是一个隐式范围,其中包含仅对线程可用的变量,并且仅在线程的生命周期内存在。您在 cfthread 标记主体内定义的任何变量,但未指定范围名称前缀,都在线程本地范围内,其他线程无法访问或修改。”所以这看起来确实可能是一个冷融合错误/问题
    • 我认为问题很复杂,因为您的线程存在于函数内部。 local 范围是基于函数的,因此不能是线程本地的。如果从cfcontent 中删除local. 会发生什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-24
    • 2017-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-28
    • 2014-01-28
    相关资源
    最近更新 更多