明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 7881|回复: 12

第十二章 反应器和回调函数 (七) 反应器使用规则

  [复制链接]
发表于 2013-1-3 14:58:50 | 显示全部楼层 |阅读模式
反应器使用规则
如我在这一章开始就提过的,反应器需要很仔细地计划和考虑其性能及稳定性。以下的指导是由AutoCAD在线帮助文件提供我,这些是很好的考虑要点。

由于将来可能修改反应器的内部实现机制,使用反应器时请尽量遵守下述规则,如果不遵守这些规则,可能会导致应用程序出现不可预料的结果。

不要依赖于反应器通报的顺序。
除了少数特例之外,建议您不要依赖于反应器通报的顺序。例如,OPEN 命令将触发 BeginCommand、BeginOpen、EndOpen 和 EndCommand 事件。然而,它们发出的顺序可能不是这样的。您可以安全地依赖的顺序只有 Begin 事件是在相应 End 事件之前发生。例如 commandWillStart() 总是在 commandEnded() 之前发生,而 beginInsert() 总是在 endInsert() 之前发生。因为将来可能引入新的事件通报,可能会重新排列现有通报顺序,所以依赖于更复杂的顺序,可能会给您的应用程序带来问题。

不要依赖于通报间函数调用的顺序。
在通报之间函数调用的顺序也是不能保证的。例如,当收到对象 A 的通报 :vlr-erased 时,它仅表示对象 A 被删除,如果在收到对象 A 的通报 :vlr-erased 之后收到了对象 B 的通报 :vlr-erased,这只是表示对象 A 和 B 都已被删除。它并不能保证 B 是在 A 后面被删除。如果应用程序依赖于这个层次的关系,那应用程序在后续版本的 AutoCAD 中很可能会崩溃。所以不要依赖于这些顺序,而应该依赖于用反应器来指示系统状态。

不要在反应器回调函数中使用任何需要和用户交互的函数(如 getPoint、entsel 等)。
在反应器回调函数中试图执行交互函数会导致严重问题,因为在事件发生时,AutoCAD 可能仍在处理某命令。所以要避免使用要求用户输入的函数,如 getPoint、entsel 和 getkword 等,也不要使用选择集操作函数和 command 函数。

在事件处理函数中不要加载对话框。
对话框和用户交互函数一样,也会影响 AutoCAD 的当前操作。然而,消息对话框和警告对话框可认为是非交互的,所以可以使用它们。

不要更新发出事件通报的对象。
引起对象触发回调函数的事件可能仍在处理之中,当调用回调函数时 AutoCAD 可能仍在使用该对象。所以,在回调函数中不要试图更新该对象。然而,您可以安全地从触发事件的对象中读取信息。例如,假设有一块用砖填充的地板,而且将反应器附着到地板边界上。如果修改地板的尺寸,反应器回调函数将自动添加或删除砖以填充新的地板面积。该函数将能获取边界的新面积,但它不能去修改边界本身。

不要在回调函数中执行能触发相同事件的操作。
如果在反应器回调函数中执行的某操作触发了同样事件,将陷入无限循环。例如,如果在 BeginOpen 事件的回调函数中试图打开一个图形,AutoCAD 将持续打开更多的图形,直到打开的图形数目达到上限,无法再打开图形为止。
  •   在设置反应器以前要确认当前没有设置该反应器,否则可能在发生同一事件时调用多个回调函数。
  •   记住当 AutoCAD 显示模式对话框时,不会发生任何事件。

注意!虽然 VLX 可能运行在和加载它的文档名称空间分开的独立名称空间中,但它仍和该文档相关联,不能操作其他文档中的对象。

AutoLISP 为运行在非激活文档中的反应器回调函数提供了有限的支持。缺省情况下,只有在定义反应器的文档是活动文档时,才会在相关事件出现时,调用反应器的回调函数。但可使用 vlr-set-notification 函数改变这种缺省行为。

为了指定某反应器在定义它的文档不是活动文档时,也能执行其回调函数(例如,其他名称空间中的应用程序触发了某事件),应调用如下函数:
(vlr-set-notification reactor-object 'all-documents)

对你的应用程序的所有实例(也就是说,如果不是一个传播到所有会话的单独命名空间VLX应用程序),通报一个事件是发生在一个会话中,这是有用的。

如果要修改反应器,使它仅在定义它的文档是活动文档时才执行其回调函数,可调用如下函数:
(vlr-set-notification reactor-object 'active-document-only)

vlr-set-notification 函数返回指定的反应器对象。例如,如下命令序列定义了一个反应器,不管与它相关联的文档是否是活动文档,该反应器都响应相关事件:
_$ (setq circleReactor (vlr-object-reactor (list myCircle)
"Circle Reactor" '((:vlr-modified . print-radius))))
#<VLR-Object-Reactor>
_$ (vlr-set-notification circleReactor 'all-documents) #<VLR-Object-Reactor>


vlr-notification 函数可确定反应器的通报设置。例如:
_$ (vlr-notification circleReactor)
all-documents


vlr-set-notification 函数仅影响它所指定的反应器,所有反应器在被创建时,其通报设置都是缺省的 "active-document-only"。

警告! 如果将某反应器设为即使其相关文档不是活动文档时,也触发其回调函数,那么该回调函数应读取或设定 AutoLISP 变量。如果它执行其他操作,可能会导致系统不稳定。



该贴已经同步到 明经通道的微博

本帖被以下淘专辑推荐:

发表于 2020-2-22 17:24:36 | 显示全部楼层
向老大致敬!
发表于 2020-2-22 17:23:23 | 显示全部楼层
向老大致敬!
发表于 2013-1-3 15:22:58 | 显示全部楼层
再抢一个沙发,好好学习下!
发表于 2013-1-3 16:13:11 | 显示全部楼层
向老大致敬!
发表于 2013-8-15 20:35:55 | 显示全部楼层
楼主真牛,支持下
发表于 2013-9-22 20:33:37 | 显示全部楼层
这个是翻译的最后一章了?
发表于 2014-6-29 16:52:57 | 显示全部楼层
还更新么?很是期待,等着学习呢!使劲顶!!!
发表于 2014-8-25 19:57:49 | 显示全部楼层
这一章比较深奥,我新手,慢慢领悟吧
发表于 2014-10-18 15:07:08 | 显示全部楼层
老大,Visual LISP开发者宝典后面的还更新吗?期待啊!有追剧的感觉!
发表于 2015-8-8 12:29:16 | 显示全部楼层
真的有用啊
发表于 2015-8-19 14:56:30 | 显示全部楼层
这是最后一部分么
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-22 15:06 , Processed in 0.211376 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表