异步绑定和存储工作原理
异步存储增强了 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 的指针:
- 名字对象本身调用 IMoniker::BindToStorage ,请求阻止 IStorage (,因为对象不是异步感知) ,创建异步存储,保留对包装对象的 IFillLockBytes 接口的引用,在根存储上注册 IProgressNotify 接口,并调用 IPersistStorage::Load,传递异步存储的 IStorage 指针。 当数据到达后台线程 (时,) 名字对象调用 IFillLockBytes 来填充临时文件中的 ILockBytes 。
- 对象从存储中读取数据,并在收到足够数据以考虑自身初始化时从 IPersistStorage::Load 返回数据。 如果对象尝试读取尚未下载的数据,则会收到 有关 IProgressNotify 的通知。 在 IProgressNotify::OnProgress 方法中,下载线程始终会阻止模式消息循环。
无论下载是同步还是异步下载,名字对象都从 IMoniker::BindToObject 返回,浏览器接收所请求的初始化对象。
浏览器查询 IOleObject 并将对象作为文档对象承载。 (此时对象可能无法完全初始化,但足以显示有用的内容,在这种情况下,下载会在后台继续。)