ColdFusion:在单独的请求中终止CFTHREAD

ColdFusion:在单独的请求中终止CFTHREAD,coldfusion,cfthread,Coldfusion,Cfthread,我正在ColdFusion应用程序中使用CFTHREAD。根据我从Ben Nadel()中读到的内容,ColdFusion只公开和跟踪当前请求中的线程。在我的情况下,我通过ajax调用生成一个线程,然后向用户提供一个cancel按钮。我希望cancel按钮可以调用线程上的terminate方法,但无论我将其存储在何处(应用程序、服务器、会话),ColdFusion总是返回一个错误,即它无法终止线程“thread\u NAME”,因为“thread\u NAME”没有生成 我知道在幕后,ColdF

我正在ColdFusion应用程序中使用CFTHREAD。根据我从Ben Nadel()中读到的内容,ColdFusion只公开和跟踪当前请求中的线程。在我的情况下,我通过ajax调用生成一个线程,然后向用户提供一个cancel按钮。我希望cancel按钮可以调用线程上的terminate方法,但无论我将其存储在何处(应用程序、服务器、会话),ColdFusion总是返回一个错误,即它无法终止线程“thread\u NAME”,因为“thread\u NAME”没有生成

我知道在幕后,ColdFusion主要是Java。所以我希望有办法。有人能证实或否认这种可能性吗?有什么例子可以说明这一点吗


谢谢

对不起,我没有50%的声誉可以评论,所以我会把这篇文章作为回答。最近,我遇到了通过ajax生成的CFThread的相同情况,我需要以某种方式终止它,但无法终止。我在CFLoop中有一个CFQuery,它在应用程序范围中使用了它的数据源。所以我想到的是登录到ColdFusion管理员并临时重命名数据源,这导致线程抛出数据库错误。虽然这是不体面的终止,但它在当时起到了作用


因此,在看到这个问题后,我开始思考一个可能的解决方法,如果没有已知的方法来实现这一点的话。假设在线程处理期间,它测试应用程序/服务器/会话范围内的变量值。假设该值最初被另一个进程设置为“true”,然后随后被另一个进程设置为“false”,当线程找到false值时,它可以正常终止。

您需要做的是在某个地方设置一个数据结构,比如应用程序或会话范围,它跟踪您希望能够取消的线程的运行情况

Application.cfc on Application Start

<cfset application.cancelThread = {} />

在输入线程之前,创建id,然后传递到线程

<cfset threadId = createUUID() />
<cfset application.cancelThread[threadId] = false />

将threadId传递回客户机以获取“取消”按钮。单击“取消”按钮后,返回threadId

<cfset application.cancelThread[form.threadId] = true />

在线程执行期间

<cfif application.cancelThread[threadId]>
    <cfabort />
    <!--- or your chosen approach to ending the processing --->
</cfif>

如果线程到达末端,则删除线程引用

<cfset structDelete(application.cancelThread, threadId) />

可以吗? 是的,但只使用内部类。创建cfthread时,使用本地THREAD_名称检索对底层THREAD对象的引用

context = getPageContext().getFusionContext();
thread = context.getUserThreadTask( "theLocalTaskName" );
由于本地名称可由多个请求使用,因此引用应存储在唯一名称下,如uuid。该引用实际上是一个内部类
coldfusion.threads.Task
的实例。要终止它,请调用其
cancel()
方法

thread.cancel();
你应该吗? 这是一个大问题,完全取决于线程做什么——它是如何做的——以及如果进程中途停止而没有任何警告,它所使用的资源将如何受到影响

原因是调用
会立即终止线程。CF不在乎它是否在临界区的中间。服务器只是用木槌敲打它,让它停下来。异常日志显示CF通过调用

java文档说
stop()
方法不推荐使用,因为:

停止线程会导致它解锁它拥有的所有监视器 锁着的。(监视器作为ThreadDeath异常解锁 向上传播堆栈。)如果以前受保护的任何对象 由于这些监视器处于不一致的状态,其他线程现在可能会 以不一致的状态查看这些对象。据说这样的物体 被损坏。当线程在损坏的对象上运行时,任意 结果可能是行为。这种行为可能很微妙,很难理解 检测,或者它可能是发音的与其他未检查的异常不同, 死亡无声地杀死线;因此,用户没有以下警告: 他的程序可能已损坏。损坏可能会在 在实际损坏发生后的任何时间,甚至是几小时或几天 未来

因此,重要的是要考虑线程实际上做了什么,并确定它是否安全终止。例如,如果线程处理带有的文件,强制终止该文件可能会阻止线程释放句柄,使底层文件处于锁定状态,这是不可取的


建议使用中断()停止java中的线程。基本上就是这个概念。中断不会强制终止线程。它只是一个表示线程停止处理的标志。让线程自己决定何时安全退出。它允许线程在终止之前完成关键部分或执行任何清理任务。是的,它需要更多的编码,但结果比“终止”更稳定和可预测。

我不确定是谁否决了你的答案,但我想说谢谢你的时间和投入。我也考虑过这个解决方案,但是我在线程中启动的进程是一个单一的连续进程,所以为了使这个方法能够工作,我需要在进程的多个位置添加一个对这个“标志”的检查。由于这将需要在所有其他将使用线程的区域上完成,我决定忘记它,让请求自己完成,而不尝试中断。谢谢你抽出时间,欢迎来到SO。@Phil谢谢你的客气话。这个问题实际上帮助了我,并让我思考,当我处于类似的情况下,如何在目前还不知道真正的解决方案时,通过提供一个变通解决方案来改变事情。希望有人能为社区提供一个比我的笨拙但实用的解决方案更优雅的基于java的答案。@user12031119-我认为被否决的人实际上没有读到答案;-)使用标志不是一个坏主意,它与java中使用的一些概念类似
"Information","cfthread-47","09/07/19","17:10:44","","THREAD_V_2: Terminated"
java.lang.ThreadDeath
  at java.base/java.lang.Thread.stop(Thread.java:942)
  at coldfusion.thread.Task.cancel(Task.java:257)
  at coldfusion.tagext.lang.ThreadTag.terminateThread(ThreadTag.java:345)
  at coldfusion.tagext.lang.ThreadTag.doStartTag(ThreadTag.java:204)