复制ColdFusion会话,以便在注销后生成线程

时间:2014-02-18 18:36:53

标签: multithreading session coldfusion

我需要在普通用户的会话中运行某些ColdFusion代码块(例如:用户点击打印并生成PDF)。该网页是互动的,用户立即获得PDF。

但是我还需要在循环内多次运行相同的代码块(超过1000次迭代)。为此,我们告诉用户完成后将向他们发送电子邮件。我以低优先级生成<cfthread>并循环相同的代码。问题是正在运行的代码在很大程度上依赖于会话范围中的变量。因此,如果用户签出,则线程错误并在遇到会话var时死亡。对于有问题的代码,我知道我可以将变量更改为不使用会话范围,然后线程将完成没有问题,但我们无法更改该代码。所以,几年前我尝试了一个有效的黑客,我从未感觉良好,并且想知道是否有人能想到更好的方法。这就是黑客...

<cfapplication name="backgroundThread" sessionTimeout="#CreateTimeSpan(0, 0, 600, 0)#" sessionManagement="Yes">

<!--- Duplicate the entire session structure --->
<cflock scope="session" timeout="30" type="Exclusive">
    <cfloop collection="#this.session#" item="session_element">
        <cfset new_session_element = evaluate("this.session." & "#session_element#")>
        <cfset "session.#session_element#" = new_session_element>
    </cfloop>
</cflock>

<cfthread action="run" priority="low" name="#this.threadid#" session=session>
  <!---
  Normal code can be included here and it will run.
  Even if the user who initiated the background process signs out.
  --->

所以基本上我创建了一个全新的应用程序/会话,然后将所有会话变量复制到这个新的应用程序/会话。因此,如果用户注销它对后台进程没有影响,那么需要会话变量的代码仍将运行。

这已经有很长一段时间了。偶尔我会研究它,但还没有找到更好的方法。在我这样的应用程序中创建应用程序似乎不对。有没有其他方法可以使用<cfapplication>代码生成新会话

我考虑过调用application.cfc->onSessionStart,但这就是Adobe所说的:如果你明确地调用这个方法,ColdFusion不会启动会话。我只需要能够产生一个新的会话,与当前用户分开,然后将大部分会话变量复制到其中。

UPDATE 2014年2月24日:我尝试了这个建议,但它仍然无效(测试是在CF10盒子上进行的)...

<cfthread action="run" name="testingSession" session="#session#" priority="LOW">
    <cfset form.session = session>  <!--- add this dirty trick --->
    <cftry>
        <cfloop from="1" to="200" index="i">
            <cfscript>sleep(3000);</cfscript>
            <cfquery name="q1" datasource="#session.sv.ds#">
                select sysdate thedate from dual
            </cfquery>
            <cflog file="threadTest6" text="thread running... #i# ... #q1.thedate#">
        </cfloop>
        <cfcatch type="any">
            <cflog file="threadTest6" text="error: #cfcatch.detail# /// #cfcatch.message#">
        </cfcatch>
    </cftry>
</cfthread>

我让该页面运行几秒钟,然后我点击了“退出”链接。我的退出流程只有这个......

<!---End session--->
<cfset StructDelete(Session, 'dev')>
<cfset StructDelete(Session, 'sv')>
<cfset StructDelete(Session, 'act')>
<cfset StructClear(Session)>
<!---I cannot use `<cfset sessionInvalidate()>` because not all our customers are up to CF10.--->

当发生这种情况时,我希望线程中的所谓重复会话继续,并且只有原始用户的会话结束。但事实并非如此。以下是threadTest6.log ...

的输出
"Severity","ThreadID","Date","Time","Application","Message"
"Information","cfthread-1","02/24/14","16:26:04",,"C:\ColdFusion10\cfusion\logs\threadTest6.log initialized"
"Information","cfthread-1","02/24/14","16:26:04","CMPRO","thread running... 1 ... 2014-02-24 16:26:04.0"
"Information","cfthread-1","02/24/14","16:26:07","CMPRO","thread running... 2 ... 2014-02-24 16:26:07.0"
"Information","cfthread-1","02/24/14","16:26:10","CMPRO","thread running... 3 ... 2014-02-24 16:26:10.0"
"Information","cfthread-1","02/24/14","16:26:13","CMPRO","thread running... 4 ... 2014-02-24 16:26:13.0"
"Information","cfthread-1","02/24/14","16:26:16","CMPRO","thread running... 5 ... 2014-02-24 16:26:16.0"
"Information","cfthread-1","02/24/14","16:26:19","CMPRO","thread running... 6 ... 2014-02-24 16:26:19.0"
"Information","cfthread-1","02/24/14","16:26:22","CMPRO","error: The value of the attribute datasource, which is currently '', is invalid. /// Attribute validation error for tag CFQUERY."

1 个答案:

答案 0 :(得分:0)

在您当前引用会话的代码中。[whatever]替换“session”的所有实例。用“myStruct”。以及“session [”with“myStruct [”的所有实例。然后在需要这些会话变量的代码块的顶部,写下以下行:

<cfparam name="myStruct" type="struct" default="#session#" />

会话结构将通过引用(而不是值)传递给本地myStruct变量。在myStruct中设置值的任何代码也将在会话范围中设置这些值。并且由于它已在请求中声明为局部变量,因此JRE将继续在结构上具有活动句柄,并且不会被垃圾收集(直到请求完成之后),即使ColdFusion可能从其清除会话队列。

如果您有引用会话范围的自定义标记,则需要将此行添加到标记中:

<cfparam name="attributes.myStruct" type="struct" default="#session#" />

然后在循环中的标记调用中指定局部变量。

如果您有引用会话范围的自定义函数或CFC,那么您需要向访问会话范围的任何方法添加可选参数:

<cfargument name="myStruct" type="struct" default="#session#" />

我错过了什么吗?我认为这些是唯一需要改变的事情。我不认为我必须解决onApplicationStartonApplicationEnd事件中不存在的会话范围问题,因为如果您在这些事件中使用此代码,则会遇到该问题。所以我认为这应该是你所需要的。

即使有成千上万的会话引用,即使在数千个文件中,也可以相对容易地完成。它只需要几个多文件搜索和替换操作,并在完成修改后进行一些测试。我以前做过这样的修改,只需要一两个小时。