Регистрация обратного вызова COM
Вместо опрашивания изменения состояния задания можно зарегистрироваться, чтобы получать уведомления при изменении состояния задания. Чтобы получить уведомление, необходимо реализовать интерфейс IBackgroundCopyCallback2. Интерфейс содержит следующие методы, которые вызываются BITS в зависимости от вашей регистрации:
Пример реализации интерфейса IBackgroundCopyCallback2 можно найти в примере кода в разделе интерфейса IBackgroundCopyCallback.
ИнтерфейсIBackgroundCopyCallback2предоставляет уведомление при передаче файла. Как правило, этот метод используется для проверки файла, чтобы файл был доступен для скачивания одноранговых узлов; в противном случае файл недоступен для одноранговых узлов, пока не вызовете метод IBackgroundCopyJob::Complete. Чтобы проверить файл, вызовите метод IBackgroundCopyFile3::SetValidationState.
Существует два метода регистрации обратного вызова COM: регистрация объекта обратного вызова или регистрация идентификатора класса обратного вызова. Использование объекта обратного вызова проще и требует меньше затрат; использование CLSID обратного вызова более надежно, но более сложно. Вы можете зарегистрировать либо один, оба, либо ни один из них – BITS будет использовать объект обратного вызова, если он существует и все еще может быть вызван, и будет создавать новый объект на основе предоставленного идентификатора класса, если это не удастся.
Регистрация объекта обратного вызова
Чтобы зарегистрировать реализацию в BITS, вызовите метод IBackgroundCopyJob::SetNotifyInterface. Чтобы указать, какие методы должен вызывать BITS, вызовите метод IBackgroundCopyJob::SetNotifyFlags.
Интерфейс уведомлений становится недействительным при завершении работы приложения; BITS не сохраняет интерфейс уведомления. В результате процесс инициализации приложения должен зарегистрировать существующие задания, для которых требуется получать уведомления. Если необходимо записать сведения о состоянии и прогрессе, которые произошли с момента последнего запуска приложения, проведите опрос состояния и прогресса во время инициализации приложения.
Перед выходом приложение должно очистить указатель интерфейса обратного вызова (SetNotifyInterface(NULL)). Более эффективно очистить указатель обратного вызова, чем позволить BITS обнаружить, что он больше не действителен.
Обратите внимание, что если несколько приложений вызывает метод SetNotifyInterface, чтобы задать интерфейс уведомлений для задания, последнее приложение для вызова метода SetNotifyInterface — это метод, который будет получать уведомления, а другие приложения не будут получать уведомления.
В следующем примере показано, как зарегистрировать уведомления. В примере предполагается, что указатель интерфейса IBackgroundCopyJob является допустимым. Дополнительные сведения о классе примера CNotifyInterface, используемом в следующем примере, см. в интерфейсе IBackgroundCopyCallback.
HRESULT hr;
IBackgroundCopyJob* pJob;
CNotifyInterface *pNotify = new CNotifyInterface();
if (pNotify)
{
hr = pJob->SetNotifyInterface(pNotify);
if (SUCCEEDED(hr))
{
hr = pJob->SetNotifyFlags(BG_NOTIFY_JOB_TRANSFERRED |
BG_NOTIFY_JOB_ERROR );
}
pNotify->Release();
pNotify = NULL;
if (FAILED(hr))
{
//Handle error - unable to register callbacks.
}
}
Регистрация CLSID обратного вызова
Чтобы зарегистрировать CLSID обратного вызова в BITS, вызовите метод IBackgroundCopyJob5::SetProperty с идентификатором свойства BITS_JOB_PROPERTY_NOTIFICATION_CLSID. Чтобы указать, какие методы вызывает BITS, вызовите метод IBackgroundCopyJob::SetNotifyFlags.
Перед регистрацией CLSID с заданием BITSID необходимо убедиться, что уведомление CLSID зарегистрировано на внепроцессном COM-сервере. Реализация COM-сервера значительно сложнее, чем определение и передача объекта обратного вызова, но предлагает несколько важных преимуществ. COM-сервер позволяет BITS поддерживать связь между заданием BITS и кодом приложения между перезагрузками системы и большими или длительными заданиями. COM-сервер также позволяет приложению полностью завершить работу, пока BITS продолжает выполнять передачу в фоновом режиме, что может улучшить использование батареи, ЦП и памяти системы.
Чтобы предоставить уведомление, на которое вы подписались для получения, BITS сначала пытается вызвать соответствующий метод любого существующего объекта обратного вызова, который вы могли прикрепить. Если нет существующего объекта или если существующий объект был отключен (обычно в результате завершения приложения), BITS вызовет CoCreateInstance, используя уведомление CLSID для создания экземпляра нового объекта обратного вызова, и будет использовать этот объект для дальнейших вызовов, пока он не отключится или пока не будет заменен новым вызовом IBackgroundCopyJob::SetNotifyInterface.
В отличие от объектов вызова, CLSID вызова сохраняются вместе с соответствующими заданиями BITS, если служба BITS или система отключаются и перезапускаются. Ваше приложение может очистить любой ранее заданный CLSID уведомлений перед выходом (или в любое другое время), установив новое значение GUID_NULL. Однако, если ваше приложение зарегистрировано для автоматического запуска COM в ответ на запросы CoCreateInstance для вашего CLSID, вы можете предпочесть оставить уведомление CLSID зарегистрированным. Обратите внимание, что если более одного приложения задаёт свойство BITS_JOB_PROPERTY_NOTIFICATION_CLSID, то последний CLSID будет тем, что BITS будет использовать для создания экземпляров объектов обратного вызова – остальные CLSID не будут использоваться. Аналогичным образом, если одно приложение регистрирует CLSID и другой регистрирует объект обратного вызова, обычные правила для объекта обратного вызова, принимающие приоритет, применяются, и CLSID не будет использоваться, если только объект обратного вызова не очищается или становится отключенным.
В следующем примере показано, как зарегистрировать уведомления CLSID. В примере предполагается, что указатель интерфейса IBackgroundCopyJob5 действителен, и что приложение уже зарегистрировано в качестве внепроцессного COM-сервера, реализующего класс CNotifyInterface. Дополнительные сведения о классе примера CNotifyInterface, используемом в следующем примере, см. в интерфейсе IBackgroundCopyCallback.
HRESULT hr;
IBackgroundCopyJob5* job;
BITS_JOB_PROPERTY_VALUE propertyValue;
propertyValue.ClsID = __uuidof(CNotifyInterface);
hr = job->SetProperty(BITS_JOB_PROPERTY_NOTIFICATION_CLSID, propertyValue);
if (SUCCEEDED(hr))
{
hr = job->SetNotifyFlags(BG_NOTIFY_JOB_TRANSFERRED |
BG_NOTIFY_JOB_ERROR);
}
if (FAILED(hr))
{
// Handle error - unable to register callbacks.
}