以非同步方式叫用服務方法
WpdServiceApiSample 應用程式包含程式碼,示範應用程式如何以非同步方式叫用服務方法。 此範例會使用下列介面。
介面 | 描述 |
---|---|
IPortableDeviceService | 用來擷取 IPortableDeviceServiceMethods 介面,以叫用指定服務上的方法。 |
IPortableDeviceServiceMethods | 用來叫用服務方法。 |
IPortableDeviceValues | 用來保存傳出方法參數和傳入方法結果。 如果方法不需要任何參數或傳回任何結果,這可以是 Null 。 |
IPortableDeviceServiceMethodCallback | 由應用程式實作,以在方法完成時接收方法結果。 |
當使用者在命令列選擇選項 「10」 時,應用程式會叫用 ServiceMethods.cpp 模組中找到的 InvokeMethodsAsync 方法。 請注意,在叫用 方法之前,範例應用程式會在連線的裝置上開啟連絡人服務。
服務方法會封裝每個服務所定義和實作的功能。 它們對每種服務類型而言都是唯一的,並以 GUID 表示。 例如,Contacts 服務會定義 BeginSync 方法,讓應用程式呼叫以準備裝置以同步處理 Contact 物件,以及 EndSync 方法,以通知裝置同步處理已完成。 應用程式會呼叫 IPortableDeviceServiceMethods::Invoke來執行可攜式裝置服務方法。
服務方法不應與 WPD 命令混淆。 WPD 命令是標準 WPD 設備磁碟機介面 (DDI) 的一部分,而且是 WPD 應用程式和驅動程式之間通訊的機制。 命令是預先定義的、依類別分組 (例如 ,WPD_CATEGORY_COMMON) ,並以 PROPERTYKEY 結構表示。 應用程式會藉由呼叫 IPortableDeviceService::SendCommand,將命令傳送至設備磁碟機。 如需詳細資訊,請參閱命令主題。
InvokeMethodsAsync方法會叫用IPortableDeviceService::Methods來擷取IPortableDeviceServiceMethods介面。 使用此介面,它會叫用 InvokeMethodAsync 協助程式函式兩次;一次用於 BeginSync 方法,一次用於 EndSync 方法。 在此範例中,呼叫IPortableDeviceServiceMethodCallback::OnComplete時,InvokeMethodAsync會無限期等候全域事件發出訊號。
下列程式碼會使用 InvokeMethodsAsync 方法。
// Invoke methods on the Contacts Service asynchornously.
// BeginSync and EndSync are methods defined by the FullEnumerationSync Device Service.
void InvokeMethodsAsync(IPortableDeviceService* pService)
{
HRESULT hr = S_OK;
CComPtr<IPortableDeviceServiceMethods> pMethods;
if (pService == NULL)
{
printf("! A NULL IPortableDeviceService interface pointer was received\n");
return;
}
// Get an IPortableDeviceServiceMethods interface from the IPortableDeviceService interface to
// invoke methods.
hr = pService->Methods(&pMethods);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceServiceMethods from IPortableDeviceService, hr = 0x%lx\n",hr);
}
// Invoke the BeginSync method asynchronously
if (SUCCEEDED(hr))
{
printf("Invoking %ws asynchronously...\n",NAME_FullEnumSyncSvc_BeginSync);
// This method does not take any parameters, so we pass in NULL
hr = InvokeMethodAsync(pMethods, METHOD_FullEnumSyncSvc_BeginSync, NULL);
if (FAILED(hr))
{
printf("! Failed to invoke %ws asynchronously, hr = 0x%lx\n",NAME_FullEnumSyncSvc_BeginSync, hr);
}
}
// Invoke the EndSync method asynchronously
if (SUCCEEDED(hr))
{
printf("Invoking %ws asynchronously...\n",NAME_FullEnumSyncSvc_EndSync);
hr = InvokeMethodAsync(pMethods, METHOD_FullEnumSyncSvc_EndSync, NULL);
if (FAILED(hr))
{
printf("! Failed to invoke %ws asynchronously, hr = 0x%lx\n",NAME_FullEnumSyncSvc_EndSync, hr);
}
}
}
InvokeMethodAsync協助程式函式會針對它叫用的每個方法執行下列動作:
- 建立全域事件控制碼,它會監視以判斷方法完成。
- 建立 CMethodCallback 物件,該物件是以 IPortableDeviceServiceMethods:InvokeAsync的引數的形式提供。
- 呼叫 IPortableDeviceServiceMethods::InvokeAsync 方法來叫用指定的方法。
- 監視全域事件控制碼以完成。
- 執行清除。
CMethodCallback類別示範應用程式如何實作IPortableDeviceServiceMethodCallback。 這個類別中的 OnComplete 實作會發出事件,通知應用程式服務方法已完成。 除了 OnComplete 方法之外,這個類別還會實作 AddRef、 QueryInterface和 Release,用來維護物件的參考計數及其實作的介面。
class CMethodCallback : public IPortableDeviceServiceMethodCallback
{
public:
CMethodCallback () : m_cRef(1)
{
}
~CMethodCallback ()
{
}
public:
// IPortableDeviceServiceMethodCallback::QueryInterface
virtual HRESULT STDMETHODCALLTYPE OnComplete(
HRESULT hrStatus,
IPortableDeviceValues* /*pResults*/) // We are ignoring results as our methods will not return any results
{
printf("** Method completed, status HRESULT = 0x%lx **\n", hrStatus);
if (g_hMethodCompleteEvent != NULL)
{
SetEvent(g_hMethodCompleteEvent);
}
return S_OK;
}
// IUnknown::AddRef
virtual ULONG STDMETHODCALLTYPE AddRef(void)
{
InterlockedIncrement((long*) &m_cRef);
return m_cRef;
}
// IUnknown::QueryInterface
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
LPVOID* ppvObj)
{
HRESULT hr = S_OK;
if (ppvObj == NULL)
{
hr = E_INVALIDARG;
return hr;
}
if ((riid == IID_IUnknown) ||
(riid == IID_IPortableDeviceServiceMethodCallback))
{
AddRef();
*ppvObj = this;
}
else
{
*ppvObj = NULL;
hr = E_NOINTERFACE;
}
return hr;
}
// IUnknown::Release
virtual ULONG STDMETHODCALLTYPE Release(void)
{
ULONG ulRefCount = m_cRef - 1;
if (InterlockedDecrement((long*) &m_cRef) == 0)
{
delete this;
return 0;
}
return ulRefCount;
}
private:
DWORD m_cRef;
};
相關主題