Sdílet prostřednictvím


Registrace zpětného volání COM

Místo dotazování o změnách ve stavu úlohy se můžete zaregistrovat, abyste dostávali oznámení, když se stav úlohy změní. Pokud chcete dostávat oznámení, musíte implementovat rozhraní IBackgroundCopyCallback2. Rozhraní obsahuje následující metody, které služba BITS volá v závislosti na vaší registraci:

Příklad implementace rozhraní IBackgroundCopyCallback2 naleznete v ukázkovém kódu v tématu rozhraní IBackgroundCopyCallback.

Rozhraní IBackgroundCopyCallback2 poskytuje oznámení při přenosu souboru. Tuto metodu obvykle použijete k ověření souboru, aby byl soubor dostupný pro uživatele ke stažení; jinak soubor nebude dostupný pro uživatele, dokud nevoláte metodu IBackgroundCopyJob::Complete. Chcete-li ověřit soubor, zavolejte metodu IBackgroundCopyFile3::SetValidationState.

Existují dvě metody registrace zpětného volání modelu COM: registrace objektu zpětného volání nebo registrace ID třídy zpětného volání. Použití objektu zpětného volání je jednodušší a snižuje režijní náklady; použití modulu CLSID zpětného volání je spolehlivější, ale složitější. Můžete zaregistrovat buď jednu, obě, nebo žádnou možnost – pokud existuje objekt zpětného volání, který může být stále volán, BITS jej použije; pokud to selže, vytvoří instanci nového objektu na základě poskytnutého ID třídy.

Registrace objektu zpětného volání

Chcete-li zaregistrovat implementaci pomocí BITS, zavolejte metodu IBackgroundCopyJob::SetNotifyInterface. Chcete-li určit, které metody BITS volá, zavolejte metodu IBackgroundCopyJob::SetNotifyFlags.

Rozhraní oznámení se po ukončení aplikace stane neplatným; BitS neuchovává rozhraní pro oznámení. V důsledku toho by měl proces inicializace vaší aplikace registrovat existující úlohy, pro které chcete dostávat oznámení. Pokud potřebujete zaznamenat informace o stavu a průběhu, ke kterým došlo od posledního spuštění aplikace, dotazujte se na informace o stavu a průběhu během inicializace aplikace.

Před ukončením by aplikace měla vymazat ukazatel rozhraní zpětného volání (SetNotifyInterface(NULL)). Je efektivnější vymazat ukazatel zpětného volání, než nechat službu BITS zjistit, že už není platná.

Všimněte si, že pokud více než jedna aplikace volá metodu SetNotifyInterface k nastavení rozhraní oznámení pro úlohu, poslední aplikace, která volá SetNotifyInterface metoda je metoda, která bude přijímat oznámení – ostatní aplikace nebudou dostávat oznámení.

Následující příklad ukazuje, jak zaregistrovat oznámení. Příklad předpokládá, IBackgroundCopyJob ukazatel rozhraní je platný. Podrobnosti o příkladové třídě CNotifyInterface použité v následujícím příkladu naleznete v rozhraní 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.
    }
}

Registrace CLSID pro zpětné volání

Chcete-li zaregistrovat CLSID zpětného volání v BITS, zavolejte IBackgroundCopyJob5::SetProperty metodou s BITS_JOB_PROPERTY_NOTIFICATION_CLSID PropertyId. Chcete-li určit, jaké metody BITS volá, zavolejte metodu IBackgroundCopyJob::SetNotifyFlags.

Musíte zajistit, že CLSID oznámení je zaregistrován u mimoprocesového serveru COM před registrací CLSID s úlohou BITS. Implementace serveru COM je výrazně složitější než definování a předávání objektu zpětného volání, ale nabízí několik důležitých výhod. Server COM umožňuje službě BITS udržovat přidružení mezi úlohou BITS a kódem vaší aplikace napříč restartováním systému a pro velké nebo dlouhodobé úlohy. Server COM také umožňuje aplikaci úplně vypnout, zatímco BITS pokračuje v provádění přenosů na pozadí, což může zlepšit využití baterie, procesoru a paměti systému.

Chcete-li poskytnout oznámení, které jste zaregistrovali k přijetí, služba BITS se nejprve pokusí volat odpovídající metodu jakéhokoli existujícího objektu zpětného volání, který jste možná připojili. Pokud neexistuje žádný objekt nebo pokud je stávající objekt odpojen (obvykle v důsledku ukončení vaší aplikace), BITS zavolá CoCreateInstance pomocí oznamovacího CLSID k vytvoření nového objektu pro zpětné volání. Tento objekt bude použit pro všechny další zpětné volání, dokud se neodpojí nebo nebude nahrazen novým voláním IBackgroundCopyJob::SetNotifyInterface.

Na rozdíl od objektů zpětného volání se CLSID zpětného volání ukládají společně s příslušnými úlohami BITS, pokud dojde k vypnutí a restartování služby BITS nebo systému. Vaše aplikace může před ukončením (nebo kdykoli jindy) vymazat jakýkoli dříve nastavený identifikátor oznámení CLSID tím, že předá nové ID oznámení GUID_NULL, ale vaše aplikace může chtít nechat oznámení CLSID zaregistrované, pokud jste registrovali, aby ji COM spustil v reakci na požadavky CoCreateInstance pro váš CLSID. Všimněte si, že pokud více než jedna aplikace nastaví vlastnost BITS_JOB_PROPERTY_NOTIFICATION_CLSID, poslední CLSID, který se nastaví, je ten, který služba BITS použije k instanci objektů zpětného volání – ostatní identifikátory CLSID instance vytvořeny nebudou. Podobně platí, že pokud jedna aplikace zaregistruje CLSID a jiný zaregistruje objekt zpětného volání, použijí se obvyklá pravidla pro objekt zpětného volání, který má přednost, a CLSID se nepoužije, pokud objekt zpětného volání nevymazá nebo se odpojí.

Následující příklad ukazuje, jak zaregistrovat oznámení CLSID. Příklad předpokládá, že ukazatel rozhraní IBackgroundCopyJob5 je platný a že se vaše aplikace již zaregistrovala jako mimoprocesový COM Server, který implementuje třídu CNotifyInterface. Podrobnosti o příkladu třídy CNotifyInterface použitého v následujícím příkladu naleznete v rozhraní 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. 
}