使用 C++ 进行半同步调用
调用 WMI 方法(如 IWbemServices::ExecMethod )和提供程序方法(如 Win32\_LogicalDisk 类的 Chkdsk 方法)时,建议采用半同步调用。
同步处理的一个缺点是:在调用完成之前,调用方线程将一直被阻止。 阻塞可能会导致处理时间延迟。 相比之下,异步调用必须在脚本中实现 SWbemSink。 在 C++ 中,异步代码必须实现 IWbemObjectSink 接口,使用多个线程,并控制信息向调用方的回流。 例如,查询中的大型结果集可能需要相当长的时间才能传递,并强制调用方花费大量系统资源来处理传递。
半同步处理可轮询实现 IWbemCallResult 接口的特殊状态对象,从而解决线程阻塞和不受控制的传递问题。 通过 IWbemCallResult,可以提高查询、枚举和事件通知的速度和效率。
以下过程介绍如何使用 IWbemServices 接口进行半同步调用。
使用 IWbemServices 接口进行半同步调用
正常进行调用,但在 IFlags 参数中设置 WBEM_FLAG_RETURN_IMMEDIATELY 标志。
可以将 WBEM_FLAG_RETURN_IMMEDIATELY 与其他对特定方法有效的标志组合在一起。 例如,对所有返回枚举器的调用使用 WBEM_FLAG_FORWARD_ONLY 标志。 组合设置这些标志可节省时间和空间,并提高响应能力。
轮询结果。
如果调用返回枚举器的方法(例如 IWbemServices::CreateClassEnum 或 IWbemServices::ExecQuery),则可以使用 IEnumWbemClassObject::Next 或 IEnumWbemClassObject::NextAsync 方法轮询枚举器。 IEnumWbemClassObject::NextAsync 调用是非阻塞的,并立即返回。 在后台,WMI 通过调用 IWbemObjectSink::Indicate 开始传递请求的对象数。 然后,WMI 停止并等待另一个 NextAsync 调用。
如果调用不返回枚举器的方法(例如 IWbemServices::GetObject),则必须将 ppCallResult 参数设置为有效的指针。 在返回的指针上使用 IWbemCallResult::GetCallStatus 以检索 WBEM_S_NO_ERROR。
完成调用。
对于返回枚举器的调用,WMI 调用 IWbemObjectSink::SetStatus 来报告操作的完成情况。 如果不需要整个结果,请通过调用 IEnumWbemClassObject::Release 方法释放枚举器。 调用 Release 会导致 WMI 取消所有剩余对象的传递。
对于不使用枚举器的调用,请通过方法的 plStatus 参数检索 GetCallStatus 对象。
本主题中的 C++ 代码示例需要以下 #include 语句才能正确编译。
#include <comdef.h>
#include <wbemidl.h>
以下代码示例演示如何以半同步方式调用 GetObject。
void GetObjSemiSync(IWbemServices *pSvc)
{
IWbemCallResult *pCallRes = 0;
IWbemClassObject *pObj = 0;
HRESULT hRes = pSvc->GetObject(_bstr_t(L"MyClass=\"AAA\""), 0,
0, 0, &pCallRes
);
if (hRes || pCallRes == 0)
return;
while (true)
{
LONG lStatus = 0;
HRESULT hRes = pCallRes->GetCallStatus(5000, &lStatus);
if ( hRes == WBEM_S_NO_ERROR || hRes != WBEM_S_TIMEDOUT )
break;
// Do another task
}
hRes = pCallRes->GetResultObject(5000, &pObj);
if (hRes)
{
pCallRes->Release();
return;
}
pCallRes->Release();
// Use the object.
// ...
// Release it.
// ===========
pObj->Release(); // Release objects not owned.
}
相关主题