第十二章 反应器和回调函数 (七) 反应器使用规则
反应器使用规则如我在这一章开始就提过的,反应器需要很仔细地计划和考虑其性能及稳定性。以下的指导是由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 变量。如果它执行其他操作,可能会导致系统不稳定。
http://bbs.mjtd.com/xwb/images/bgimg/icon_logo.png 该贴已经同步到 明经通道的微博 向老大致敬! 向老大致敬! 再抢一个沙发,好好学习下! 向老大致敬! 楼主真牛,支持下 这个是翻译的最后一章了? 还更新么?很是期待,等着学习呢!使劲顶!!! 这一章比较深奥,我新手,慢慢领悟吧 老大,Visual LISP开发者宝典后面的还更新吗?期待啊!有追剧的感觉! 真的有用啊 这是最后一部分么
页:
[1]
2