Compartilhar via


Registrando um retorno de chamada COM

Em vez de pesquisar alterações no status de um trabalho, você pode se registrar para receber notificações quando o status do trabalho for alterado. Para receber a notificação, você deve implementar a interface IBackgroundCopyCallback2. A interface contém os seguintes métodos que o BITS chama, dependendo do seu registro:

Para obter um exemplo que implementa a interface IBackgroundCopyCallback2, consulte o código de exemplo no tópico da interface IBackgroundCopyCallback.

A interface IBackgroundCopyCallback2 fornece notificação quando um arquivo é transferido. Normalmente, você usa esse método para validar o arquivo, para que o arquivo esteja disponível para pares baixarem; caso contrário, o arquivo não estará disponível para pares até que você chame o método IBackgroundCopyJob::Complete . Para validar o arquivo, chame o método IBackgroundCopyFile3::SetValidationState.

Há dois métodos para registrar um retorno de chamada COM: registrar um objeto de retorno de chamada ou registrar uma ID de classe de retorno de chamada. Usar um objeto de retorno de chamada é mais simples e reduz a sobrecarga; usar um CLSID de retorno de chamada é mais confiável, mas mais complicado. Você pode registrar ambos, ou nenhum dos dois – o BITS usará um objeto de retorno de chamada se existir e ainda puder ser chamado, e voltará a instanciar um novo objeto com base em uma ID de classe fornecida se isso falhar.

Registrando um objeto de retorno de chamada

Para registrar sua implementação com o BITS, chame o método IBackgroundCopyJob::SetNotifyInterface. Para especificar quais métodos o BITS chama, chame o método IBackgroundCopyJob::SetNotifyFlags.

A interface de notificação torna-se inválida quando o aplicativo é encerrado; O BITS não persiste a interface de notificação. Como resultado, o processo de inicialização do aplicativo deve registrar trabalhos existentes para os quais você deseja receber notificação. Se você precisar capturar informações de estado e progresso que ocorreram desde a última vez que seu aplicativo foi executado, pesquise informações de estado e progresso durante a inicialização do aplicativo.

Antes de sair, seu aplicativo deve limpar o ponteiro da interface de retorno de chamada (SetNotifyInterface(NULL)). É mais eficiente limpar o ponteiro de retorno de chamada do que permitir que o BITS descubra que ele não é mais válido.

Observe que, se mais de um aplicativo chamar o método SetNotifyInterface para definir a interface de notificação para o trabalho, o último aplicativo a chamar o método SetNotifyInterface será aquele que receberá notificações — os outros aplicativos não receberão notificações.

O exemplo a seguir mostra como se registrar para notificações. O exemplo assume que o ponteiro da interface IBackgroundCopyJob é válido. Para obter detalhes sobre a classe de exemplo CNotifyInterface usada no exemplo a seguir, consulte a interface 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.
    }
}

Registrando um CLSID de retorno de chamada

Para registrar um CLSID de retorno de chamada com o BITS, chame o método IBackgroundCopyJob5::SetProperty com o BITS_JOB_PROPERTY_NOTIFICATION_CLSID PropertyId. Para especificar quais métodos o BITS chama, chame o método IBackgroundCopyJob::SetNotifyFlags.

Você deve garantir que o CLSID de notificação seja registrado em um servidor COM fora de processo antes de registrar o CLSID com um trabalho do BITS. A implementação de um servidor COM é significativamente mais complicada do que definir e passar um objeto de retorno de chamada, mas oferece várias vantagens importantes. Um servidor COM permite que o BITS mantenha a associação entre um trabalho do BITS e o código do aplicativo em reinicializações do sistema e para trabalhos grandes ou de longa duração. Um servidor COM também permite que seu aplicativo seja desligado completamente enquanto o BITS continua executando transferências em segundo plano, o que pode melhorar o uso da bateria, CPU e memória do sistema.

Para fornecer uma notificação que você registrou para receber, o BITS primeiro tenta chamar o método correspondente de qualquer objeto de retorno de chamada existente que você possa ter anexado. Se não houver nenhum objeto existente, ou se esse objeto existente tiver se desconectado (normalmente como resultado do encerramento do aplicativo), o BITS chamará CoCreateInstance usando o CLSID de notificação para instanciar um novo objeto de retorno de chamada e usará esse objeto para quaisquer retornos de chamada adicionais até que ele seja desconectado ou seja substituído por uma nova chamada para IBackgroundCopyJob:: SetNotifyInterface.

Ao contrário dos objetos de retorno de chamada, o CLSID de retorno de chamada é persistido ao lado de seus trabalhos BITS correspondentes se o serviço BITS ou o sistema forem desligados e reiniciados. Seu aplicativo pode limpar qualquer CLSID de notificação definido anteriormente antes de sair (ou em qualquer outro momento) passando um novo CLSID de notificação de GUID_NULL, mas seu aplicativo pode preferir deixar o CLSID de notificação registrado se seu aplicativo tiver se registrado para que o COM o inicie em resposta às solicitações CoCreateInstance para seu CLSID. Observe que, se mais de um aplicativo definir as chamadas da propriedade BITS_JOB_PROPERTY_NOTIFICATION_CLSID , o último CLSID a ser definido será aquele que o BITS usará para instanciar objetos de retorno de chamada – os outros CLSIDs não serão instanciados. Da mesma forma, se um aplicativo registrar um CLSID e outro registrar um objeto de retorno de chamada, as regras usuais para o objeto de retorno de chamada que tem precedência se aplicarão, e o CLSID não será usado, a menos que o objeto de retorno de chamada seja limpo ou seja desconectado.

O exemplo a seguir mostra como registrar notificações CLSID. O exemplo assume que o ponteiro da interface IBackgroundCopyJob5 é válido e que seu aplicativo já foi registrado como um servidor COM fora de processo que implementa a classe CNotifyInterface. Para obter detalhes sobre a classe de exemplo CNotifyInterface usada no exemplo a seguir, consulte a interface 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. 
}