Поделиться через


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

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

Одним из недостатков синхронной обработки является блокировка потока вызывающего объекта до завершения вызова. Блокировка может привести к задержке во время обработки. В отличие от этого, асинхронный вызов должен реализовывать 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::Укажите. Затем WMI останавливается и ожидает другого вызова NextAsync.

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

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

    Для вызова, возвращающего перечислитель, WMI вызывает IWbemObjectSink::SetStatus, чтобы сообщить о завершении операции. Если вам не нужен весь результат, освободите перечислитель, вызвав метод IEnumWbemClassObject::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.            
  
}

вызов метода