Создание полусинхронного вызова с помощью C++

Полусинхронные вызовы являются рекомендуемыми средствами для вызова методов WMI, таких как IWbemServices::ExecMethod , и методов поставщика, таких как метод Chkdsk класса Win32_LogicalDisk.

Одним из недостатков синхронной обработки является то, что вызывающий поток блокируется до завершения вызова. Блокировка может привести к задержке времени обработки. В отличие от этого, асинхронный вызов должен реализовывать SWbemSink в скрипте. В C++ асинхронный код должен реализовывать интерфейс IWbemObjectSink , использовать несколько потоков и управлять потоком информации, возвращаемой вызывающей стороне. Например, большие результирующие наборы из запросов могут занять значительное количество времени и заставить вызывающий объект тратить значительные системные ресурсы на обработку доставки.

Полусинхронная обработка решает проблемы с блокировкой потока и неконтролируемой доставкой путем опроса специального объекта состояния, реализующего интерфейс IWbemCallResult . С помощью IWbemCallResult можно повысить скорость и эффективность запросов, перечислений и уведомлений о событиях.

В следующей процедуре описывается, как выполнить полусинхронный вызов с помощью интерфейса IWbemServices .

Создание полусинхронного вызова с помощью интерфейса IWbemServices

  1. Выполните вызов обычным образом, но с флагом WBEM_FLAG_RETURN_IMMEDIATELY , установленным в параметре IFlags .

    Вы можете объединить WBEM_FLAG_RETURN_IMMEDIATELY с другими флагами, допустимыми для конкретного метода. Например, используйте флаг WBEM_FLAG_FORWARD_ONLY для всех вызовов, возвращающих перечислители. Установка этих флагов в сочетании экономит время и пространство, а также повышает скорость реагирования.

  2. Опрос результатов.

    При вызове метода, возвращающего перечислитель, например IWbemServices::CreateClassEnum или IWbemServices::ExecQuery, можно опросить перечислители с помощью методов IEnumWbemClassObject::Next или IEnumWbemClassObject::NextAsync . Вызов IEnumWbemClassObject::NextAsync не блокируется и возвращается немедленно. В фоновом режиме WMI начинает доставлять запрошенное количество объектов путем вызова IWbemObjectSink::Indicate. Затем WMI останавливается и ожидает другого вызова NextAsync .

    При вызове метода, который не возвращает перечислитель, например IWbemServices::GetObject, необходимо задать для параметра ppCallResult допустимый указатель. Используйте IWbemCallResult::GetCallStatus для возвращаемого указателя, чтобы получить WBEM_S_NO_ERROR.

  3. Завершите звонок.

    Для вызова, возвращающего перечислитель, 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.            
  
}

Вызов метода