- 积分
- 13326
- 明经币
- 个
- 注册时间
- 2015-8-18
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
本帖最后由 你有种再说一遍 于 2025-3-19 19:15 编辑
在cad.net开发中,
由于大部分人都没有接受过训练就上战场,
例如引入不同的包功能,使得项目变得越来越复杂.
同时还允许我们比Lisp更自由操作内存(非托管内存).
这样使得一旦出问题,我们debug非常困难.
一些常规的规范操作,
例如能using就绝对不手工释放.
要手工释放的就最好写入Disposable的派生类中,
外部执行using,从而达到规范化.
还有一些难以启齿的错误,
由于.net不是可观可测系统,
我们不能直接通过GC内存使用前后量来判断.
也无法像C++一样重定向new关键字,
此时就需要挂不同的事件进行debug了.
利用:
命令前事件,记录命令到日志.
命令结束后,记录命令到日志.
当发生异常的时候,
你检查日志就可以知道哪个命令没有正常结束,
或者命令结束后仍然发生了错误,也可以检查命令链.
例如内存泄露并不是必显的,
这样起码缩小范围到命令链中多个命令.
一些不良习惯喜欢把
var a = new...
a = new... // 弄丢了原始指针
a.Dispose()
再例如,我们通过tr.GetObject(id)进行打开对象,
那么哪个命令打开对象之后没有释放呢?
我们就可以挂命令后事件,
然后每次检查一次这个tr.GetAllObjects()数量,
数量不为0才报错.
如果觉得每次触发命令都序列化太伤硬盘,
我们就利用消息队列,传递给其他进程让其惰性序列化.
毕竟宕机是少数,我们保护等级不需要像数据库一样每每写入.
利用统计,除了日志找bug之外.
还可以回放动作,看看播放你全部命令之后,能否复现问题.
还可以优化频率高的命令,从而改变你的"画图手法".
命令是Acad系统中重要概念,
命令实际上是一个消息队列,
它会投递到在Acad主线程中执行,
而界面上面触发,要发送命令,而不是直接执行函数,
函数的运行不一定在主线程触发.
这关系到线程上下文问题.
CommandFlags中有无历史命令,你可以隐匿在界面的执行.
事件可以拦截cad自带的命令,
而消息过程可以拦截函数异常,
Fody可以拦截报错.
例如重置用户配置后发生错误.
此类错误还可以尝试去钩一下消息过程,
毕竟经常勾着它,它可能给你带来不一样debug点子.
xx |
|