Fazer uma chamada semissíncrona com C++
Chamadas semissíncronas são os meios recomendados para chamar métodos WMI, como IWbemServices::ExecMethod e métodos de provedor, como o método Chkdsk da classe Win32_LogicalDisk.
Uma desvantagem do processamento síncrono é que o thread do chamador é bloqueado até que a chamada seja concluída. O bloqueio pode causar um atraso no tempo de processamento. Por outro lado, uma chamada assíncrona deve implementar SWbemSink no script. Em C++, o código assíncrono deve implementar a interface IWbemObjectSink, usar vários threads e controlar o fluxo de informações de volta para o chamador. Grandes conjuntos de resultados de consultas, por exemplo, podem levar um tempo considerável para entregar e força o chamador a gastar recursos significativos do sistema para lidar com a entrega.
O processamento semissíncrono resolve o bloqueio de thread e os problemas de entrega não controlados sondando um objeto de status especial que implementa a interface IWbemCallResult. Por meio de IWbemCallResult, você pode melhorar a velocidade e a eficiência de consultas, enumerações e notificações de eventos.
O procedimento a seguir descreve como fazer uma chamada semissíncrona com a interface IWbemServices.
Para fazer uma chamada semissíncrona com a interface IWbemServices
Faça sua chamada normalmente, mas com o sinalizador WBEM_FLAG_RETURN_IMMEDIATELY definido no parâmetro IFlags.
Você pode combinar WBEM_FLAG_RETURN_IMMEDIATELY com outros sinalizadores válidos para o método específico. Por exemplo, use o sinalizador WBEM_FLAG_FORWARD_ONLY para todas as chamadas que retornam enumeradores. Definir esses sinalizadores em combinação economiza tempo e espaço e melhora a capacidade de resposta.
Sonde seus resultados.
Se chamar um método que retorna um enumerador, como IWbemServices::CreateClassEnum ou IWbemServices::ExecQuery, você poderá sondar os enumeradores com os métodos IEnumWbemClassObject::Next ou IEnumWbemClassObject::NextAsync. A chamada IEnumWbemClassObject::NextAsync não está sendo desbloqueada e retorna imediatamente. Em segundo plano, o WMI começa a entregar o número solicitado de objetos chamando IWbemObjectSink::Indicate. Em seguida, o WMI para e aguarda outra chamada NextAsync.
Se você chamar um método que não retorna um enumerador, como IWbemServices::GetObject, defina o parâmetro ppCallResult como um ponteiro válido. Use IWbemCallResult::GetCallStatus no ponteiro retornado para recuperar WBEM_S_NO_ERROR.
Conclua sua chamada.
Para uma chamada que retorna um enumerador, o WMI chama IWbemObjectSink::SetStatus para relatar a conclusão da operação. Se você não precisar do resultado inteiro, libere o enumerador chamando o método IEnumWbemClassObject::Release. Chamar Release resulta no cancelamento pelo WMI da entrega de todos os objetos restantes.
Para uma chamada que não usa um enumerador, recupere o objeto GetCallStatus por meio do parâmetro plStatus do método.
O exemplo de código C++ neste tópico requer que as instruções #include a seguir sejam compiladas corretamente.
#include <comdef.h>
#include <wbemidl.h>
O exemplo de código a seguir mostra como fazer uma chamada semissíncrona para 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.
}
Tópicos relacionados