Antarmuka IBackgroundCopyCallback (bits.h)

Terapkan antarmuka IBackgroundCopyCallback untuk menerima pemberitahuan bahwa pekerjaan selesai, telah dimodifikasi, atau dalam kesalahan. Klien menggunakan antarmuka ini alih-alih polling untuk status pekerjaan.

Warisan

Antarmuka IBackgroundCopyCallback mewarisi dari antarmuka IUnknown . IBackgroundCopyCallback juga memiliki jenis anggota ini:

Metode

Antarmuka IBackgroundCopyCallback memiliki metode ini.

 
IBackgroundCopyCallback::JobError

BITS memanggil implementasi metode JobError Anda ketika status pekerjaan berubah menjadi BG_JOB_STATE_ERROR.
IBackgroundCopyCallback::JobModification

BITS memanggil implementasi metode JobModification Anda ketika pekerjaan telah dimodifikasi.
IBackgroundCopyCallback::JobTransferred

BITS memanggil implementasi metode JobTransferred Anda ketika semua file dalam pekerjaan telah berhasil ditransfer.

Keterangan

Untuk menerima pemberitahuan, panggil metode IBackgroundCopyJob::SetNotifyInterface untuk menentukan penunjuk antarmuka ke implementasi IBackgroundCopyCallback Anda. Untuk menentukan pemberitahuan mana yang ingin Anda terima, panggil metode IBackgroundCopyJob::SetNotifyFlags .

BITS akan memanggil panggilan balik Anda selama penunjuk antarmuka valid. Antarmuka pemberitahuan tidak lagi valid ketika aplikasi Anda berakhir; BITS tidak mempertahankan antarmuka pemberitahuan. Akibatnya, proses inisialisasi aplikasi Anda harus memanggil metode SetNotifyInterface pada pekerjaan yang ada yang ingin Anda terima pemberitahuannya.

BITS menjamin untuk memanggil panggilan balik Anda setidaknya sekali, bahkan jika pendaftaran terjadi setelah peristiwa. Misalnya, jika Anda meminta pemberitahuan transfer pekerjaan setelah transfer terjadi, Anda akan menerima panggilan balik yang ditransfer pekerjaan. Selain itu, jika pekerjaan menerima pemberitahuan dan pointer kemudian tidak lagi valid, pekerjaan tersebut akan menerima pemberitahuan lain jika Anda kemudian mengatur penunjuk antarmuka pada pekerjaan tersebut.

Anda harus menerapkan semua metode antarmuka IBackgroundCopyCallback . Misalnya, jika Anda tidak mendaftar untuk panggilan balik modifikasi pekerjaan, metode JobModification masih harus mengembalikan S_OK.

Panggilan balik JobModification diluncurkan menggunakan utas prioritas rendah sedangkan panggilan balik JobTransferred dan JobError diluncurkan menggunakan utas prioritas yang lebih tinggi. Jadi ada kemungkinan bahwa sementara beberapa panggilan balik JobModification menunggu panggilan balik JobTransferred diterima oleh klien terlebih dahulu meskipun diluncurkan setelah panggilan balik JobModification yang tertunda.

BITS mendukung hingga empat pemberitahuan simultan per pengguna. Jika satu atau beberapa aplikasi memblokir keempat pemberitahuan untuk pengguna agar tidak kembali, aplikasi yang berjalan sebagai pengguna yang sama tidak akan menerima pemberitahuan sampai satu atau beberapa pemberitahuan pemblokiran kembali. Untuk mengurangi kemungkinan panggilan balik Anda memblokir pemberitahuan lain, jaga agar implementasi Anda tetap singkat.

Jika administrator mengambil kepemilikan pekerjaan, panggilan balik pemberitahuan dibuat dalam konteks pengguna yang meminta pemberitahuan.

Jika aplikasi Anda menggunakan model apartemen berulir tunggal , metode panggilan balik Anda dapat menjadi reentrant jika Anda memanggil objek COM dari dalam metode panggilan balik Anda. Misalnya, jika Anda memanggil IBackgroundCopyJob::GetProgress dari dalam panggilan balik JobModification Anda, BITS dapat mengirim panggilan balik modifikasi pekerjaan Anda pemberitahuan lain saat Anda masih memproses pemberitahuan saat ini. Jika tidak penting bagi aplikasi Anda untuk menanggapi setiap panggilan balik JobModification , Anda dapat mengabaikan panggilan balik masuk kembali seperti yang ditunjukkan dalam contoh berikut.

//A member variable is used to determine if the callback
//is already processing another job modification callback.
LONG m_PendingJobModificationCount = 0;

//If you are already processing a callback, ignore this notification.
if (InterlockedCompareExchange(&m_PendingJobModificationCount, 1, 0) == 1)
{
  return S_OK;
}

...  //processing the current notification

m_PendingJobModificationCount = 0;
return hr;

Contoh

Contoh berikut menunjukkan implementasi IBackgroundCopyCallback . Untuk contoh yang memanggil implementasi ini, lihat metode IBackgroundCopyJob::SetNotifyInterface .

#define TWO_GB 2147483648    // 2GB


class CNotifyInterface : public IBackgroundCopyCallback
{
  LONG m_lRefCount;

public:
  //Constructor, Destructor
  CNotifyInterface() {m_lRefCount = 1;};
  ~CNotifyInterface() {};

  //IUnknown
  HRESULT __stdcall QueryInterface(REFIID riid, LPVOID *ppvObj);
  ULONG __stdcall AddRef();
  ULONG __stdcall Release();

  //IBackgroundCopyCallback methods
  HRESULT __stdcall JobTransferred(IBackgroundCopyJob* pJob);
  HRESULT __stdcall JobError(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError);
  HRESULT __stdcall JobModification(IBackgroundCopyJob* pJob, DWORD dwReserved);
};

HRESULT CNotifyInterface::QueryInterface(REFIID riid, LPVOID* ppvObj) 
{
  if (riid == __uuidof(IUnknown) || riid == __uuidof(IBackgroundCopyCallback)) 
  {
    *ppvObj = this;
  }
  else
  {
    *ppvObj = NULL;
    return E_NOINTERFACE;
  }

  AddRef();
  return NOERROR;
}

ULONG CNotifyInterface::AddRef() 
{
  return InterlockedIncrement(&m_lRefCount);
}

ULONG CNotifyInterface::Release() 
{
  ULONG  ulCount = InterlockedDecrement(&m_lRefCount);

  if(0 == ulCount) 
  {
    delete this;
  }

  return ulCount;
}

HRESULT CNotifyInterface::JobTransferred(IBackgroundCopyJob* pJob)
{
  HRESULT hr;

  //Add logic that will not block the callback thread. If you need to perform
  //extensive logic at this time, consider creating a separate thread to perform
  //the work.

  hr = pJob->Complete();
  if (FAILED(hr))
  {
    //Handle error. BITS probably was unable to rename one or more of the 
    //temporary files. See the Remarks section of the IBackgroundCopyJob::Complete 
    //method for more details.
  }

  //If you do not return S_OK, BITS continues to call this callback.
  return S_OK;
}

HRESULT CNotifyInterface::JobError(IBackgroundCopyJob* pJob, IBackgroundCopyError* pError)
{
  HRESULT hr;
  BG_FILE_PROGRESS Progress;
  BG_ERROR_CONTEXT Context;
  HRESULT ErrorCode = S_OK;
  WCHAR* pszJobName = NULL;
  WCHAR* pszErrorDescription = NULL;
  BOOL IsError = TRUE;

  //Use pJob and pError to retrieve information of interest. For example,
  //if the job is an upload reply, call the IBackgroundCopyError::GetError method 
  //to determine the context in which the job failed. If the context is 
  //BG_JOB_CONTEXT_REMOTE_APPLICATION, the server application that received the 
  //upload file failed.

  hr = pError->GetError(&Context, &ErrorCode);

  //If the proxy or server does not support the Content-Range header or if
  //antivirus software removes the range requests, BITS returns BG_E_INSUFFICIENT_RANGE_SUPPORT.
  //This implementation tries to switch the job to foreground priority, so
  //the content has a better chance of being successfully downloaded.
  if (BG_E_INSUFFICIENT_RANGE_SUPPORT == ErrorCode)
  {
    hr = pError->GetFile(&pFile);
    hr = pFile->GetProgress(&Progress);
    if (BG_SIZE_UNKNOWN == Progress.BytesTotal)
    {
      //The content is dynamic, do not change priority. Handle as an error.
    }
    else if (Progress.BytesTotal > TWO_GB)
    {
      // BITS requires range requests support if the content is larger than 2 GB.
      // For these scenarios, BITS uses 2 GB ranges to download the file,
      // so switching to foreground priority will not help.

    }
    else
    {
      hr = pJob->SetPriority(BG_JOB_PRIORITY_FOREGROUND);
      hr = pJob->Resume();
      IsError = FALSE;
    }

    pFile->Release();
  }

  if (TRUE == IsError)
  {
    hr = pJob->GetDisplayName(&pszJobName);
    hr = pError->GetErrorDescription(LANGIDFROMLCID(GetThreadLocale()), &pszErrorDescription);

    if (pszJobName && pszErrorDescription)
    {
      //Do something with the job name and description. 
    }

    CoTaskMemFree(pszJobName);
    CoTaskMemFree(pszErrorDescription);
  }

  //If you do not return S_OK, BITS continues to call this callback.
  return S_OK;
}

HRESULT CNotifyInterface::JobModification(IBackgroundCopyJob* pJob, DWORD dwReserved)
{
  HRESULT hr;
  WCHAR* pszJobName = NULL;
  BG_JOB_PROGRESS Progress;
  BG_JOB_STATE State;

  hr = pJob->GetDisplayName(&pszJobName);
  if (SUCCEEDED(hr))
  {
    hr = pJob->GetProgress(&Progress);
    if (SUCCEEDED(hr))
    {
      hr = pJob->GetState(&State);
      if (SUCCEEDED(hr))
      {
        //Do something with the progress and state information.
        //BITS generates a high volume of modification
        //callbacks. Use this callback with discretion. Consider creating a timer and 
        //polling for state and progress information.
      }
    }
    CoTaskMemFree(pszJobName);
  }

  return S_OK;
}

Persyaratan

Persyaratan Nilai
Klien minimum yang didukung Windows XP
Server minimum yang didukung Windows Server 2003
Target Platform Windows
Header bits.h

Lihat juga

IBackgroundCopyJob

IBackgroundCopyJob::SetNotifyFlags

IBackgroundCopyJob::SetNotifyInterface