异步调用服务方法
WpdServiceApiSample 应用程序包含演示如何应用程序异步调用服务方法的代码。 此示例使用以下接口。
接口 | 说明 |
---|---|
IPortableDeviceService | 用于检索 IPortableDeviceServiceMethods 接口,以调用给定服务上的方法。 |
IPortableDeviceServiceMethods | 用于调用服务方法。 |
IPortableDeviceValues | 用于保存传出方法参数和传入方法结果。 如果方法不需要任何参数或返回任何结果,则此值可以为 NULL 。 |
IPortableDeviceServiceMethodCallback | 由应用程序实现,以在方法完成时接收方法结果。 |
当用户在命令行中选择选项“10”时,应用程序将调用 ServiceMethods.cpp 模块中找到的 InvokeMethodsAsync 方法。 请注意,在调用方法之前,示例应用程序会在连接的设备上打开联系人服务。
服务方法封装每个服务定义和实现的功能。 它们对每种类型的服务都是唯一的,由 GUID 表示。 例如,联系人服务定义一个 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;
};
相关主题