Как работает система асинхронной привязки и хранения?
Асинхронное хранилище улучшает спецификацию структурированного хранилища COM для поддержки загрузки объектов хранилища в сетях с высокой задержкой, медленных каналах, таких как Интернет. Асинхронное хранилище работает вместе с асинхронными моникерами для обеспечения полного асинхронного механизма привязки.
Объект документа, внедренный на веб-страницу
Когда пользователь щелкает ссылку, представляющую документ, внедренный на веб-страницу, происходят следующие события:
Браузер вызывает функцию MkParseDisplayName, передав URL-адрес ссылки.
MkParseDisplayName анализирует URL-адрес, создает соответствующий асинхронный моникер и возвращает указатель на интерфейс IMoniker моникера .
Браузер вызывает IsAsyncMoniker, чтобы определить, является ли моникер асинхронным, создает контекст привязки, регистрирует интерфейс IBindStatusCallback в контексте привязки, только если моникер является асинхронным, и вызывает IMoniker::BindToObject, передав контекст привязки.
Моникер привязывается к объекту и запрашивает его для интерфейса IPersistMoniker, который указывает, поддерживает ли объект асинхронную привязку и хранилище. Если объект возвращает указатель на IPersistMoniker:
- Моникер URL-адреса вызывает IPersistMoniker::Load, передав собственный IMoniker указатель на объект.
- Объект изменяет контекст привязки, выбирает, хочет ли он блокировать или неблокировать хранилище, регистрирует собственный IBindStatusCallback и вызывает IMoniker::BindToStorage на указателе, который он получил через IPersistMoniker::Load.
- Моникер создает асинхронное хранилище, сохраняет ссылку на интерфейс IFillLockBytes объекта-оболочки, регистрирует интерфейс IProgressNotify в корневом хранилище и вызывает IPersistStorage::Load, передав указатель IStorage асинхронного хранилища. По мере поступления данных (в фоновом потоке) моникер вызывает IFillLockBytes для заполнения ILockBytes в temp-файле.
- Объект считывает данные из хранилища и возвращает данные из 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 и размещает объект в виде объекта Document. (На этом этапе объект может не инициализироваться полностью, но достаточно, чтобы отобразить что-то полезное, в этом случае скачивание продолжается в фоновом режиме.)