IBackgroundCopyCallback2 인터페이스(bits3_0.h)
파일 다운로드가 완료되었다는 알림을 받으 려면 이 인터페이스를 구현합니다. 클라이언트는 파일의 다운로드 상태 폴링하는 대신 이 인터페이스를 사용합니다.
알림을 받으려면 IBackgroundCopyJob::SetNotifyInterface 메서드를 호출하여 IBackgroundCopyCallback 구현에 대한 인터페이스 포인터를 지정합니다. 수신할 알림을 지정하려면 IBackgroundCopyJob::SetNotifyFlags 메서드를 호출합니다 .
이 인터페이스 및 IBackgroundCopyCallback 인터페이스의 모든 메서드를 구현해야 합니다. 예를 들어 전송된 파일 콜백에 등록하지 않은 경우 FileTransferred 메서드는여전히 S_OK 반환해야 합니다. 전송된 파일 콜백을 받지 않으려면 IBackgroundCopyCallback 을 대신 구현하면 됩니다.
상속
IBackgroundCopyCallback2 인터페이스는 IBackgroundCopyCallback에서 상속됩니다. IBackgroundCopyCallback2 에는 다음과 같은 유형의 멤버도 있습니다.
메서드
IBackgroundCopyCallback2 인터페이스에는 이러한 메서드가 있습니다.
IBackgroundCopyCallback2::FileTransferred BITS는 BITS가 파일 전송을 성공적으로 완료할 때 FileTransferred 메서드의 구현을 호출합니다. |
설명
이 인터페이스 구현에 대한 자세한 내용은 IBackgroundCopyCallback 인터페이스를 참조하세요.
예제
다음 예제에서는 IBackgroundCopyCallback2 구현을 보여줍니다. 이 예제에서는 단일 스레드 아파트 모델에 대한 JobModification 콜백에서 재진입 호출을 처리하는 방법도 보여 드립니다.
#define TWO_GB 2147483648 // 2GB
class CNotifyInterface : public IBackgroundCopyCallback2
{
LONG m_lRefCount;
LONG m_PendingJobModificationCount;
public:
//Constructor, Destructor
CNotifyInterface() {m_lRefCount = 1; m_PendingJobModificationCount = 0;};
~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 __stdcall FileTransferred(IBackgroundCopyJob* pJob, IBackgroundCopyFile* pFile);
};
HRESULT CNotifyInterface::QueryInterface(REFIID riid, LPVOID* ppvObj)
{
if (riid == __uuidof(IUnknown) ||
riid == __uuidof(IBackgroundCopyCallback) ||
riid == __uuidof(IBackgroundCopyCallback2))
{
*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 does not use range requests if the content is less than 2 GB.
//However, if the content is greater than 2 GB, 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;
//If you are already processing a callback, ignore this notification.
if (InterlockedCompareExchange(&m_PendingJobModificationCount, 1, 0) == 1)
{
return S_OK;
}
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);
}
m_PendingJobModificationCount = 0;
return S_OK;
}
HRESULT CNotifyInterface::FileTransferred(IBackgroundCopyJob* pJob, IBackgroundCopyFile* pFile)
{
HRESULT hr = S_OK;
IBackgroundCopyFile3* pFile3 = NULL;
BOOL IsValid = FALSE;
hr = pFile->QueryInterface(__uuidof(IBackgroundCopyFile3), (void**)&pFile3);
if (SUCCEEDED(hr))
{
// Add code to validate downloaded content and set IsValid.
hr = pFile3->SetValidationState(IsValid);
if (FAILED(hr))
{
// Handle error
}
pFile3->Release();
}
return S_OK;
}
요구 사항
요구 사항 | 값 |
---|---|
지원되는 최소 클라이언트 | Windows Vista |
지원되는 최소 서버 | Windows Server 2008 |
대상 플랫폼 | Windows |
헤더 | bits3_0.h(Bits.h 포함) |