我正在尝试编写一个包含后台线程的dm脚本,如以下示例代码所示。在此代码中,我想在关闭图像窗口时停止后台线程。我认为在这种情况下可能需要一些事件监听器。您能建议我如何通过关闭图像窗口事件来控制(即停止)后台线程吗?如果您可以建议对我的代码进行一些修改或显示您的示例代码,我将感谢您的合作。
// $BACKGROUND$
//
Class CBackground : Thread
{
Number isRunning
Number imgID
Image tmpIMG
//
Void Init( Object self, Number iID ){
imgID = iID
tmpIMG := GetImageFromID( imgID )
}
//
Void StopRunning( Object self ){
isRunning = 0
}
//
Number GetIsRunning( Object self ){
return isRunning
}
//
Void RunThread( Object self ){
Result("Background thread is starting ......")
isRunning = 1
while (isRunning)
{
tmpIMG = random()
sleep(0.5)
}
Result(" finished !!" + "\n")
}
}
//
Void Main(){
Object cbkg = alloc(CBackground)
Image IMG := RealImage("test",4,64,64)
IMG = random()
IMG.ShowImage()
IMG.SetWindowSize(512,512)
cbkg.Init(IMG.GetImageID())
cbkg.StartThread()
}
//
Main()
答案 0 :(得分:1)
您不能从该线程之外停止后台线程,即您不能中断一个线程。为了停止后台线程,相应的代码需要具有停止条件并退出自身。
为了从另一个线程引导此停止条件,您需要以某种方式在两个线程之间“通信”。这可以通过许多不同的方式来完成。最简单的方法是使用一个简单的数字变量,该变量由后台运行代码检查,但可以通过任何其他“外部”代码进行设置。 An example for this can be found in this answer here。
除了使用简单的变量,还可以使用一些常见的位置,例如f.e. 全局标签。另外,还为脚本语言定义了一些更复杂的线程同步对象,例如 signals , mutexes 和 semphores ,并在此处的帮助文档中进行了描述:
如何外部线程可以将“中断”插入到后台运行线程中,这也可以通过许多不同的方式来完成。如上例所示,一种是通过一些打开的对话框进行用户交互。正如作者所提到的,另一种方法是具有一些事件侦听器代码来触发此事件。 以下示例在图像上附加了一个键侦听器,以便(此图像位于最前面并处于选中状态)用户可以按ESC按钮停止线程。
我正在使用提供的脚本进行最少的修改来显示此内容:
// $BACKGROUND$
//
Class CBackground : Thread
{
Number isRunning
Number imgID
Number keyListenID
Image tmpIMG
//
Void Init( Object self, Number iID ){
imgID = iID
tmpIMG := GetImageFromID( imgID )
ImageDisplay disp = tmpIMG.ImageGetImageDisplay(0)
keyListenID = disp.ImageDisplayAddKeyHandler( self, "KeyListenAction" )
}
//
Void StopRunning( Object self ){
isRunning = 0
}
//
Number GetIsRunning( Object self ){
return isRunning
}
/////////////////////////////////////////////////////////////////////////////
Number KeyListenAction(Object self, ImageDisplay disp, Object keydesc )
{
number b_keyhandled = 0
If ( keydesc.MatchesKeyDescriptor("esc") )
{
disp.ImageDisplayRemoveKeyHandler( keyListenID )
self.StopRunning()
Result( "\nSend stopping flag, unregister Key-Listeners" )
b_keyhandled = 1
}
return b_keyhandled;
}
//
Void RunThread( Object self ){
Result("Background thread is starting ......")
isRunning = 1
while (isRunning)
{
tmpIMG = random()
sleep(0.5)
}
Result(" finished !!" + "\n")
}
}
//
Void Main(){
Object cbkg = alloc(CBackground)
Image IMG := RealImage("test",4,64,64)
IMG = random()
IMG.ShowImage()
IMG.SetWindowSize(512,512)
cbkg.Init(IMG.GetImageID())
cbkg.StartThread()
}
//
Main()
但是,有些事情我会有所不同:
答案 1 :(得分:1)
这是使用 window-closed 侦听器中止任务的脚本示例。
{
"compilerOptions": {
"outDir": "build/dist",
"module": "esnext",
"target": "es2018",
"lib": ["esnext", "dom"],
"sourceMap": true,
"allowJs": true,
"jsx": "react",
"moduleResolution": "node",
"rootDir": "src",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": false, //here
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"noUnusedParameters": true
},
"exclude": [
"node_modules",
"build",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/setupTests.ts"
]
}