revit官方案例githup库
如果你曾经在Revit API的开发过程中,遇到过"Cannot execute Revit API outside of Revit API context"这样的异常,这个异常抛出的一个典型场景是当你尝试在非模态窗体中调用Revit API,那么这个库也许能够帮到你。
上面这个异常,对Revit API不熟悉的新开发者会感到困惑,他们可能并不理解ExternalEvent.Raise()的真正含义。ExternalEvent.Raise()方法,并不马上执行你写在IExternalEventHandler.Execute()方法中的代码,而是把预先注册好的IExternalEventHandler实例,添加到Revit内部的任务队列中,Revit会以单线程的方式,循环地从任务队列顶部抓取一个IExternalEventHandler实例,执行Execute方法。换言之,ExternalEvent.Raise()只是发起了一个异步任务。
但是Revit API提供的IExternalEventHandler接口过于简单(方法签名void Execute(UIApplication app)),使得基于此接口的业务实现,很难动态地获取参数,也很难返回某一次执行的结果,必须要借助第三方的数据转存才能实现业务逻辑的串联,这使得本来连贯的业务开发,变得支离破碎。
如果你熟悉JavaScript ES6提供的Promise异步以及浏览器异步渲染机制,或者你理解.NET中的Task异步任务以及桌面STA应用的异步渲染机制,你就会发现,Revit提供的ExternalEvent与上述两种异步机制何其相似,我们完全可以基于Revit提供的异步能力,结合.NET基于任务的异步模型,提供一套更加简单易用的异步调用机制,以取代羸弱的ExternalEvent。
Revit.Async这个库,正是对这套异步机制的一种实现,重点解决外部事件传参以及外部事件结果的回调,使得开发者可以更加自然地基于Revit API书写代码,而不必被Revit API的执行上下文所困扰。Revit.Async这个库内部,会自动将待执行的方法,委托给内部定义的特定外部事件,Raise这个事件之后,立即向调用方返回一个用于接收事件回调的Task,调用方只需要await这个Task,即可在外部事件处理完成之后,获取结果并继续剩下的其他业务逻辑。