异步绑定和存储的工作原理
异步存储增强了 COM 结构化存储规范,以支持在 Internet 等高延迟、慢链接网络上下载存储对象。 异步存储与异步名字对象协同工作,以提供完整的异步绑定行为。
网页中嵌入的文档对象
当用户单击表示网页中嵌入的文档的链接时,会发生以下事件:
浏览器调用 MkParseDisplayName 函数,传递链接 URL。
MkParseDisplayName 分析 URL,创建相应的异步名字对象,并返回指向名字对象的 IMoniker 接口的指针。
浏览器调用 IsAsyncMoniker 以确定名字对象是否是异步的,创建绑定上下文,仅当名字对象为异步时才向绑定上下文注册 IBindStatusCallback 接口,并调用 IMoniker::BindToObject,传递绑定上下文。
名字对象绑定到 对象,并查询 IPersistMoniker 接口,该接口指示对象是否支持异步绑定和存储。 如果对象返回指向 IPersistMoniker 的指针:
- URL 名字对象调用 IPersistMoniker::Load,将自己的 IMoniker 指针传递给对象。
- 对象修改绑定上下文,选择是需要阻止存储还是非阻止存储,注册自己的 IBindStatusCallback ,并在它通过 IPersistMoniker:: Load 接收的指针上调用 IMoniker::BindToStorage。
- 名字对象创建异步存储,保留对包装器对象的 IFillLockBytes 接口的引用,在根存储上注册 IProgressNotify 接口,并调用 IPersistStorage::Load,传递异步存储的 IStorage 指针。 当数据到达后台线程 () 名字对象调用 IFillLockBytes 以填充临时文件中的 ILockBytes 。
- 对象从存储中读取数据,并在收到足够的数据认为自身已初始化时从 IPersistMoniker::Load 返回。 如果对象尝试读取尚未下载的数据,则下载器会在 IProgressNotify 上收到通知。 在 IProgressNotify::OnProgress 方法中,下载线程在模式消息循环中阻塞,或导致异步存储返回E_PENDING,具体取决于对象是请求阻止存储还是非阻止存储。
如果对象未实现 IPersistMoniker,则名字对象将查询 IPersistStorage,这指示对象的持久状态存储在存储对象中。 如果对象返回指向 IPersistStorage 的指针:
- Moniker 在自身上调用 IMoniker::BindToStorage ,请求阻止 IStorage (因为对象不是异步感知) ,创建异步存储,保留对包装器对象的 IFillLockBytes 接口的引用,在根存储上注册 IProgressNotify 接口,并调用 IPersistStorage::Load,传递异步存储的 IStorage 指针。 当数据到达后台线程 () 名字对象调用 IFillLockBytes 以填充临时文件上的 ILockBytes 。
- 对象从存储中读取数据,并在收到足够的数据认为自身已初始化时从 IPersistStorage::Load 返回。 如果对象尝试读取尚未下载的数据,它将在 IProgressNotify 上收到通知。 在 IProgressNotify::OnProgress 方法中,下载线程始终阻止在模式消息循环中。
无论下载是同步的还是异步的,名字对象都会从 IMoniker::BindToObject 返回,并且浏览器会接收它请求的初始化对象。
浏览器查询 IOleObject 并将对象作为 Document 对象托管。 (此时,对象可能无法完全初始化,但足以显示有用内容,在这种情况下,在后台继续下载。)