masterlong 发表于 2021-12-10 11:23:38

哪怕程序出错也强制让它完成到底

昨天编了一个程序急用
主要是对随机图元进行打断、拉伸等随机操作
打断位置、拉伸的向量都是随机计算的
时间关系
很多操作都是用command来完成的
程序编完调试发现
由于缺少对操作对象的判定
程序会时不时出错中断
花了点时间纠错但是没能完成
一怒之下将程序结构改成出错也强制执行到底
现将关键思路放上来
供大家参考

方法其实也很简单
出错函数放到主程序之外
并如下定义
(defun *error*(msg)
(vla-sendcommand *doc* "自定义命令 ")
)
主程序中可能出错的循环
不使用while、mapcar、foreach
而是使用repeat
并将循环次数设定为《总数-当前计数》

模拟代码如下
(defun c:moni()   ;;定义一个外壳程序来调用主程序
(moni_err)    ;;对error的重定义,不要放到主程序里
(c:moni_main)
(moni_no_err)
(princ)
)
(defun c:moni_main()
(if (null curr_w) (setq curr_w 0));;外循环计数
(if (null curr_n) (setq curr_n 0));;内循环计数

(repeat (- tot_w外循环总次数 curr_w)
(repeat (- tot_n内循环总次数 curr_n)
   (dosomething1)
   (setq curr_n (1+ curr_n))
)
(dosomething2)

(setq curr_w (1+ curr_w))
(setq curr_n 0)
)

;;内外循环完成后计数归0
(setq curr_w 0)
(setq curr_n 0)
(princ)
)
(defun moni_err()
(setq idx_err 0)
(setq moniolderr *error* )

(defun *error*(msg)
;;(setq curr_n (1+ curr_n))   ;;如果需要跳过上次出错位置,取消句首屏蔽
(setq idx_err (1+ idx_err))   ;;出错计数
(vla-sendcommand *doc* "moni_main ");;出错后用vla-sendcommand强制执行主程序
)
   (defun moni_no_err()
(setq *error* moniolderr)
(if (< 0 idx_err) (princ idx_err))   ;;报告出错次数
   )
(princ)
)

菜卷鱼 发表于 2021-12-13 09:17:58

;;我的话,会这么弄
(defun c:tt nil
(setq a (strcat 1 2 3))
(setq b 1)
(setq c 2)
(princ a)
(prin1)
)

;;正常的话,运行第一句(setq a (strcat 1 2 3)) ,程序就中断了
;;b ,c就不会有值

;;利用vl-catch-all-apply出错也可以运行的原理
;;程序改造一下

(defun tryexp (x / catch)
(vl-catch-all-apply
    '(lambda () (setq catch (eval x)))
)
catch
)

(defun c:tt nil
(mapcar 'tryexp
          '(
          (setq a (strcat 1 2 3))
          (setq b 1)
          (setq c 2)
          (princ a)
           )
)
(prin1)
)




masterlong 发表于 2021-12-19 21:13:06

本帖最后由 masterlong 于 2021-12-19 21:19 编辑

这个本质上是不一样的
你是在主程序中跳过出错
让程序在错误的情况下不发生“中断”

而我的方法
是在程序发生中断以后
再次调用主程序
让它接着或者跳过出错的位置往下运行

我的方法适用于大量循环的情况
即使是按了ESC试图中断
都能坚挺地继续
除此之外
还可以比较方便的建立出错日志

vl~apply也能做到记录错误
但是要麻烦很多

并不是说我的方法更好
而是要看具体的应用场景
正如首贴中我说的
作为一个临时性的应急程序
确实本身就不那么严谨
也没有时间去优化
每一步都在生成随机数
在随机区域中对随机图元执行随机操作
复制、移动、缩放、旋转、拉伸、打断、延伸
出错的可能太多太多

另外再说一点
vl~apply也不是万能的
最近两天我编程时就遇到一个怪事
代码上看没有一点问题
比如对块执行(vla-get-isxref blkobj)
结果偏偏就是出错
命令行单步执行
提示是“ActiveX 服务器返回错误:未知名称:Isxref”
也就是说“ActiveX 服务器本身出了错”
就因为这里的代码用了vl~apply去监测
返回的永远都是“错误”
导致程序运行结果始终不符合预期
而且怎么也查不出出错根源
debug好久才确定了不是代码的问题
最终只能改变程序流程绕开vla-get-*
这种情况以前也碰到过
但都属于偶发性
出错的原因至今不清楚





jh3030912 发表于 2023-8-30 22:07:41

怎么使用呢?这个?

wzg356 发表于 2023-8-31 17:38:31

jh3030912 发表于 2023-8-30 22:07
怎么使用呢?这个?

一般不需要,编程碰上无伤害的出错也无所谓且需要继续的时候才需要
页: [1]
查看完整版本: 哪怕程序出错也强制让它完成到底