Поделиться через


Регистрация обратного вызова 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 PropertyId. Чтобы указать методы BITS, вызовите метод IBackgroundCopyJob::SetNotifyFlags .

Перед регистрацией CLSID с заданием BITSID необходимо убедиться, что уведомление CLSID зарегистрировано на внепроцессном COM-сервере. Реализация COM-сервера значительно сложнее, чем определение и передача объекта обратного вызова, но предлагает несколько важных преимуществ. COM-сервер позволяет BITS поддерживать связь между заданием BITS и кодом приложения между перезагрузками системы и большими или длительными заданиями. COM-сервер также позволяет приложению полностью завершить работу, пока BITS продолжает выполнять передачу в фоновом режиме, что может улучшить использование батареи, ЦП и памяти системы.

Чтобы предоставить уведомление, которое вы зарегистрировали для получения, BITS сначала пытается вызвать соответствующий метод любого существующего объекта обратного вызова, который вы могли подключить. Если нет существующего объекта или если существующий объект стал отключен (обычно в результате завершения приложения), BITS вызовет CoCreateInstance с помощью clSID уведомления, чтобы создать экземпляр нового объекта обратного вызова, и будет использовать этот объект для дальнейших обратных вызовов, пока он не будет отключен или заменен новым вызовом iBackgroundCopyJob:: SetNotifyInterface.

В отличие от объектов обратного вызова, clSID обратного вызова сохраняются вместе с соответствующими заданиями BITS, если служба BITS или система завершаются и перезапускаются. Ваше приложение может очистить любой ранее заданный clSID перед выходом (или в любое другое время), передав новое уведомление CLSID GUID_NULL, но ваше приложение может предпочесть оставить уведомление CLSID зарегистрированным, если приложение зарегистрировало com-запуск в ответ на запросы CoCreateInstance для 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. 
}