2012-11-12 58 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