共用方式為


使用 C++ 進行半同步呼叫

半異步呼叫是呼叫 WMI 方法的建議方法,例如 IWbemServices::ExecMethod 和提供者方法,例如 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::CreateClassEnumIWbemServices::ExecQuery,您可以使用 IEnumWbemClassObject::NextIEnumWbemClassObject::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.            
  
}

呼叫方法