Udostępnij przez


Wykonywanie wywołania semisynchronicznego za pomocą języka C++

Wywołania semisynchroniczne to zalecany sposób wywoływania metod WMI, takich jak IWbemServices::ExecMethod, oraz metod dostarczanych przez dostawcę, takich jak metoda Chkdsk klasy Win32_LogicalDisk.

Jedną wadą synchronicznego przetwarzania jest zablokowanie wątku wywołującego do momentu zakończenia wywołania. Blokada może spowodować opóźnienie w czasie przetwarzania. Natomiast wywołanie asynchroniczne musi implementować SWbemSink w skrypcie. W języku C++kod asynchroniczny musi implementować interfejs IWbemObjectSink, używać wielu wątków i kontrolować przepływ informacji z powrotem do obiektu wywołującego. Duże zestawy wyników z zapytań mogą zająć dużo czasu na dostarczenie i zmuszają obiekt wywołujący do znacznego wykorzystania zasobów systemowych w celu obsługi dostarczania wyników.

Przetwarzanie semisynchroniczne rozwiązuje zarówno problemy z blokowaniem wątku, jak i niekontrolowanym dostarczaniem, sondując specjalny obiekt stanu, który implementuje interfejs IWbemCallResult. Za pośrednictwem IWbemCallResultmożna poprawić szybkość i wydajność zapytań, wyliczeń i powiadomień o zdarzeniach.

Poniższa procedura opisuje sposób wykonywania wywołania semisynchronicznego za pomocą interfejsu IWbemServices.

Aby wykonać wywołanie semisynchroniczne za pomocą interfejsu IWbemServices

  1. Wykonaj połączenie jak zwykle, ale ustaw flagę WBEM_FLAG_RETURN_IMMEDIATELY w parametrze IFlags.

    Można połączyć WBEM_FLAG_RETURN_IMMEDIATELY z innymi flagami, które są prawidłowe dla określonej metody. Na przykład użyj flagi WBEM_FLAG_FORWARD_ONLY dla wszystkich wywołań, które zwracają enumeratory. Ustawienie tych flag w kombinacji pozwala zaoszczędzić czas i przestrzeń oraz poprawić czas reakcji.

  2. Sonduj wyniki.

    Jeśli wywołasz metodę zwracającą moduł wyliczający, taki jak IWbemServices::CreateClassEnum lub IWbemServices::ExecQuery, możesz sondować moduły wyliczające za pomocą metody IEnumWbemClassObject::Next lub IEnumWbemClassObject::NextAsync. Wywołanie IEnumWbemClassObject::NextAsync nie jest blokujące i zwraca natychmiast. W tle usługa WMI zaczyna dostarczać żądaną liczbę obiektów, wywołując IWbemObjectSink::Indicate. Następnie usługa WMI zatrzymuje się i czeka na następne wywołanie NextAsync.

    W przypadku wywołania metody, która nie zwraca modułu wyliczającego, takiego jak IWbemServices::GetObject, należy ustawić parametr ppCallResult na prawidłowy wskaźnik. Użyj IWbemCallResult::GetCallStatus zwróconego wskaźnika, aby pobrać WBEM_S_NO_ERROR.

  3. Zakończ połączenie.

    W przypadku wywołania, które zwraca enumerator, usługa WMI wywołuje IWbemObjectSink::SetStatus, aby zgłosić zakończenie operacji. Jeśli nie potrzebujesz całego wyniku, zwolnij moduł wyliczający, wywołując metodę IEnumWbemClassObject::Release. Wywołanie Release powoduje, że usługa WMI anuluje dostarczanie wszystkich pozostałych obiektów.

    W przypadku wywołania, które nie używa modułu wyliczającego, pobierz obiekt GetCallStatus za pomocą parametru plStatus metody.

Przykładowy kod języka C++ w tym temacie wymaga poprawnego skompilowania poniższych instrukcji #include.

#include <comdef.h>
#include <wbemidl.h>

Poniższy przykład kodu pokazuje, jak wykonać wywołanie semisynchroniczne w celu 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.            
  
}

Wywołanie metody