C++를 사용하여 반동기 호출 수행
반동기 호출은 IWbemServices::ExecMethod와 같은 WMI 메서드와 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.
}
관련 항목