Создание полусинхронного вызова с помощью C++
Полусинхронные вызовы являются рекомендуемыми средствами для вызова методов WMI, таких как IWbemServices::ExecMethod , и методов поставщика, таких как метод Chkdsk класса Win32_LogicalDisk.
Одним из недостатков синхронной обработки является то, что вызывающий поток блокируется до завершения вызова. Блокировка может привести к задержке времени обработки. В отличие от этого, асинхронный вызов должен реализовывать SWbemSink в скрипте. В C++ асинхронный код должен реализовывать интерфейс IWbemObjectSink , использовать несколько потоков и управлять потоком информации, возвращаемой вызывающей стороне. Например, большие результирующие наборы из запросов могут занять значительное количество времени и заставить вызывающий объект тратить значительные системные ресурсы на обработку доставки.
Полусинхронная обработка решает проблемы с блокировкой потока и неконтролируемой доставкой путем опроса специального объекта состояния, реализующего интерфейс IWbemCallResult . С помощью IWbemCallResult можно повысить скорость и эффективность запросов, перечислений и уведомлений о событиях.
В следующей процедуре описывается, как выполнить полусинхронный вызов с помощью интерфейса IWbemServices .
Создание полусинхронного вызова с помощью интерфейса IWbemServices
Выполните вызов обычным образом, но с флагом WBEM_FLAG_RETURN_IMMEDIATELY , установленным в параметре IFlags .
Вы можете объединить 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 отменяет доставку всех оставшихся объектов.
Для вызова, который не использует перечислитель, извлеките объект GetCallStatus с помощью параметра plStatus метода .
Для правильной компиляции в примере кода 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.
}
Связанные темы