C++를 사용하여 반동기 호출 수행

반동기 호출은 IWbemServices::ExecMethod와 같은 WMI 메서드와 Win32_LogicalDisk 클래스의 Chkdsk 메서드와 같은 공급자 메서드를 호출할 때 권장되는 방법입니다.

동기 처리의 한 가지 단점은 호출이 완료될 때까지 호출자 스레드가 차단된다는 것입니다. 차단으로 인해 처리 시간이 지연될 수 있습니다. 반면에 비동기 호출은 스크립트에서 SWbemSink를 구현해야 합니다. C++에서 비동기 코드는 IWbemObjectSink 인터페이스를 구현하고, 여러 스레드를 사용하고, 정보의 흐름을 제어하여 호출자에게 돌려주어야 합니다. 예를 들어, 쿼리에서 발생한 대규모 결과 집합은 전달하는 데 상당한 시간이 걸릴 수 있으며 호출자가 전달을 처리하기 위해 상당한 시스템 리소스를 사용하도록 강제할 수 있습니다.

반동기 처리는 IWbemCallResult 인터페이스를 구현하는 특수 상태 개체를 폴링하여 스레드 차단 문제와 전달이 제어되지 않는 문제를 모두 해결합니다. IWbemCallResult를 사용하여 쿼리, 열거형 및 이벤트 알림의 속도와 효율성을 향상할 수 있습니다.

다음 절차에서는 IWbemServices 인터페이스를 사용하여 반동기 호출을 수행하는 방법을 설명합니다.

IWbemServices 인터페이스를 사용하여 반동기 호출을 수행하려면 다음을 수행합니다.

  1. IFlags 매개 변수에 설정된 WBEM_FLAG_RETURN_IMMEDIATELY 플래그를 사용하여 평상시와 같이 호출합니다.

    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가 남아 있는 모든 개체의 전달을 취소합니다.

    열거자를 사용하지 않는 호출에 대해서는 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.            
  
}

메서드 호출