我认为您遇到的问题是粒子分析(至少部分)在单独的后台线程上运行。
我不相信在这种情况下有办法直接捕获这些异常。
我不再使用 GMS 1.84,但我确实在 GMS 3.2 上进行了一些尝试,您可能还想这样做以更好地了解正在发生的事情。
首先,您的 Try/Catch 循环是可以的,但是如果您没有在 catch 中放置“中断”,那么一旦离开了 catch 部分,异常将被提升到系统,即您经常想做的事:
Try{
... }
Catch{
...
break
}
...
为了测试脚本如何处理来自被调用方法的异常,我首先编写了一个小脚本并将其“安装”为菜单命令,一次使用后台线程,一次不使用后台线程。我通过 Custom 菜单中的 File-menu 分别使用命令名称 BT 和 nBT 安装了它们:
// $BACKGROUND$
Result( "\nStart and wait" )
number i = 0
while( i < 100 ){
i++
sleep(0.05)
if ( ShiftDown() ) break
if ( OptionDown() ) Throw("Broken")
Result( "." )
}
Result("\nDone and exit.")
和
Result( "\nStart and wait" )
number i = 0
while( i < 100 ){
i++
sleep(0.05)
if ( ShiftDown() ) break
if ( OptionDown() ) Throw("Broken")
Result( "." )
}
Result("\nDone and exit.")
然后我使用“ChooseMenuItem()”在以下脚本中进行测试:
string name = TwoButtonDialog("Background threaded?", "yes", "no" ) ? "BT" : "nBT"
number success = 0
Try{
Result( "\n Calling: " + name )
success = ChooseMenuItem("Custom","",name)
}
catch
{
Result("\n Caught exception." )
break
}
result("\n Success: " + success )
使用此组合进行测试(并使用 ALT 键在例程中引发异常)我可以验证命令的行为应符合预期:
- 如果由
ChooseMenuItem 命令启动的例程在主线程上启动,则该调用的执行会“阻塞”主脚本直到它完成 - 无论是在其结束时,或者当它抛出异常时。主脚本正确捕获异常并打印结果。
- 如果由
ChooseMenuItem 命令启动的例程在单独的(后台)线程上启动,则主脚本会立即继续。 ChooseMenuItem 立即成功返回(如果它可以启动命令),并退出 Try/Catch 循环。后台线程上被调用例程抛出的任何异常都将不再被捕获。
至于错误的根源:“无效索引”消息指向某个对象正在被主脚本删除(或保留在范围内),而该主脚本预计被调用的背景存在(或不再存在)常规。这可以是图像或 imageDocument 或图像的显示或图像显示上的任何对象(ROI、掩码...)。
我怀疑您的主脚本正在执行诸如关闭使用过的图像之类的操作?如果“分析”在单独的线程上,则您的主脚本可能太快或太慢,导致事情不同步。您可能需要在主脚本中添加人为暂停 (sleep()) 和更复杂的图像跟踪系统(使用 image-IDs )以避免此类事情。
使用ChooseMenuItem() 是一种变通的破解解决方案,因此任何针对您的问题的错误预防解决方案都可能也是需要一些丑陋的“创造性”的代码破解。