Exécution d’un appel semi-synchrone avec C++

Les appels semi-synchrones constituent le moyen recommandé d’appeler des méthodes WMI, telles que les méthodes IWbemServices::ExecMethod et de fournisseur, telles que la méthode Chkdsk de la classe Win32\_LogicalDisk.

L’un des inconvénients du traitement synchrone est que le thread de l’appelant est bloqué jusqu’à la fin de l’appel. Le blocage peut entraîner un retard dans le temps de traitement. En revanche, un appel asynchrone doit implémenter SWbemSink dans le script. En C++, le code asynchrone doit implémenter l’interface IWbemObjectSink, utiliser plusieurs threads et contrôler le flux d’informations renvoyé vers l’appelant. Les jeux de résultats volumineux provenant de requêtes, par exemple, peuvent prendre beaucoup de temps et forcent l’appelant à dépenser des ressources système importantes pour gérer la remise.

Le traitement semi-synchrone résout à la fois le blocage de thread et les problèmes de remise non contrôlée en interrogeant un objet d’état spécial qui implémente l’interface IWbemCallResult. Grâce à IWbemCallResult, vous pouvez améliorer la vitesse et l’efficacité des requêtes, des énumérations et des notifications d’événements.

La procédure suivante décrit comment effectuer un appel semi-synchrone avec l’interface IWbemServices.

Pour effectuer un appel semi-synchrone avec l’interface IWbemServices

  1. Effectuez votre appel de façon normale, mais avec l’indicateur WBEM_FLAG_RETURN_IMMEDIATELY défini dans le paramètre IFlags.

    Vous pouvez combiner WBEM_FLAG_RETURN_IMMEDIATELY avec d’autres indicateurs valides pour la méthode spécifique. Par exemple, utilisez l’indicateur WBEM_FLAG_FORWARD_ONLY pour tous les appels qui retournent des énumérateurs. La définition combinée de ces indicateurs permet de gagner du temps et de l’espace, et d’améliorer la réactivité.

  2. Interrogez vos résultats.

    Si vous appelez une méthode qui retourne un énumérateur, tel que IWbemServices::CreateClassEnum ou IWbemServices::ExecQuery, vous pouvez interroger les énumérateurs avec les méthodes IEnumWbemClassObject::Next ou IEnumWbemClassObject::NextAsync. L’appel IEnumWbemClassObject::NextAsync n’est pas bloquant et retourne immédiatement. En arrière-plan, WMI commence à remettre le nombre d’objets demandé en appelant IWbemObjectSink::Indicate. WMI arrête et attend un autre appel NextAsync.

    Si vous appelez une méthode qui ne retourne pas d’énumérateur, telle que IWbemServices::GetObject, vous devez définir le paramètre ppCallResult sur un pointeur valide. Utilisez IWbemCallResult::GetCallStatus sur le pointeur retourné pour récupérer WBEM_S_NO_ERROR.

  3. Terminez votre appel.

    Pour un appel qui retourne un énumérateur, WMI appelle IWbemObjectSink::SetStatus pour signaler la fin de l’opération. Si vous n’avez pas besoin du résultat entier, libérez l’énumérateur en appelant la méthode IEnumWbemClassObject::Release. L’appel de Release entraîne l’annulation par WMI de la remise de tous les objets qui restent.

    Pour un appel qui n’utilise pas d’énumérateur, récupérez l’objet GetCallStatus via le paramètre plStatus de votre méthode.

L’exemple de code C++ de cette rubrique nécessite la compilation correcte des instructions #include suivantes.

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

L’exemple de code suivant montre comment effectuer un appel semi-synchrone à 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.            
  
}

Appel d’une méthode