Partilhar via


Executando operações assíncronas

Aplica-se a:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsSistema de Plataforma de Análise (PDW)Base de dados SQL no Microsoft Fabric

Baixar driver OLE DB

O SQL Server permite que as aplicações realizem operações assíncronas em bases de dados. O processamento assíncrono permite que os métodos retornem imediatamente sem serem bloqueados no thread que chama. Isto permite grande parte da potência e flexibilidade do multithreading, sem exigir que o programador crie explicitamente threads ou trate da sincronização. As aplicações solicitam processamento assíncrono ao inicializar uma ligação a uma base de dados ou ao inicializar o resultado da execução de um comando.

Abrir e Fechar uma Ligação à Base de Dados

Ao utilizar o OLE DB Driver para SQL Server, aplicações concebidas para inicializar um objeto fonte de dados de forma assíncrona podem definir o bit DBPROPVAL_ASYNCH_INITIALIZE na propriedade DBPROP_INIT_ASYNCH antes de chamar IDBInitialize::Initialize. Quando esta propriedade é definida, o fornecedor retorna imediatamente da chamada para Inicializar com S_OK, se a operação tiver sido concluída imediatamente, ou DB_S_ASYNCHRONOUS, se a inicialização continuar assíncrona. As aplicações podem consultar a interface IDBAsynchStatus ou ISSAsynchStatus no objeto fonte de dados e depois chamar IDBAsynchStatus::GetStatus ou ISSAsynchStatus::WaitForAsynchCompletion para obter o estado da inicialização.

Além disso, a propriedade SSPROP_ISSAsynchStatus foi adicionada ao conjunto de propriedades DBPROPSET_SQLSERVERROWSET. Os fornecedores que suportam a interface ISSAsynchStatus devem implementar esta propriedade com um valor de VARIANT_TRUE.

IDBAsynchStatus::Abort ou ISSAsynchStatus::Abort podem ser chamados para cancelar a chamada Initialize assíncrona. O consumidor deve solicitar explicitamente a Inicialização da Fonte de Dados Assíncrona. Caso contrário, IDBInitialize::Initialize não retorna até que o objeto fonte de dados esteja completamente inicializado.

Observação

Os objetos fonte de dados usados para pooling de ligações não podem chamar a interface ISSAsynchStatus no Driver OLE DB para SQL Server. A interface ISSAsynchStatus não está exposta para objetos de fonte de dados agrupados.

Se uma aplicação forçar explicitamente a utilização do motor de cursores, IOpenRowset::OpenRowset e IMultipleResults::GetResult não suportarão processamento assíncrono.

Além disso, o proxy remoto/dll de stub (no MDAC 2.8) não pode chamar a interface ISSAsynchStatus no OLE DB Driver para SQL Server. A interface ISSAsynchStatus não é exposta através do remoto.

Os Componentes de Serviço não suportam ISSAsynchStatus.

Execução e inicialização de conjuntos de linhas

Aplicações concebidas para abrir assíncronamente o resultado da execução de um comando podem definir o bit DBPROPVAL_ASYNCH_INITIALIZE na propriedade DBPROP_ROWSET_ASYNCH. Ao definir este bit antes de chamar IDBInitialize::Initialize, ICommand::Execute, IOpenRowset::OpenRowset ou IMultipleResults::GetResult, o argumento riid deve ser definido como IID_IDBAsynchStatus, IID_ISSAsynchStatus ou IID_IUnknown.

O método retorna imediatamente com S_OK se a inicialização do conjunto de linhas for concluída imediatamente, ou com DB_S_ASYNCHRONOUS se o conjunto de linhas continuar a inicializar assíncronamente, com o ppRowset definido para a interface solicitada no conjunto de linhas. Para o Driver OLE DB para SQL Server, esta interface só pode ser IDBAsynchStatus ou ISSAsynchStatus. Até que o conjunto de linhas esteja totalmente inicializado, esta interface comporta-se como se estivesse num estado suspenso, e chamar QueryInterface para interfaces que não sejam IID_IDBAsynchStatus ou IID_ISSAsynchStatus pode devolver E_NOINTERFACE. A menos que o consumidor solicite explicitamente processamento assíncrono, o conjunto de linhas é inicializado de forma síncrona. Todas as interfaces solicitadas estão disponíveis quando IDBAsynchStatus::GetStatus ou ISSAsynchStatus::WaitForAsynchCompletion regressam com a indicação de que a operação assíncrona está concluída. Isto não significa necessariamente que o conjunto de linhas esteja totalmente preenchido, mas sim completo e totalmente funcional.

Se o comando executado não devolver um conjunto de linhas, ele devolve imediatamente um objeto que suporta IDBAsynchStatus.

Se precisar de obter múltiplos resultados da execução assíncrona de comandos, deve:

  • Defina o bit DBPROPVAL_ASYNCH_INITIALIZE da propriedade DBPROP_ROWSET_ASYNCH antes de executar o comando.

  • Ligue para o ICommand::Execute e solicite IMultipleResults.

As interfaces IDBAsynchStatus e ISSAsynchStatus podem então ser obtidas consultando a interface de múltiplos resultados usando o QueryInterface.

Quando o comando termina de ser executado, o IMultipleResults pode ser usado normalmente, com uma exceção do caso síncrono: DB_S_ASYNCHRONOUS pode ser devolvido, caso em que IDBAsynchStatus ou ISSAsynchStatus podem ser usados para determinar quando a operação está completa.

Examples

No exemplo seguinte, a aplicação chama um método não bloqueante, faz algum outro processamento e depois regressa para processar os resultados. ISSAsynchStatus::WaitForAsynchCompletion espera no objeto de evento interno até que a operação em execução assíncrona seja concluída ou até que o tempo especificado por dwMilisecTimeOut seja passado.

// Set the DBPROPVAL_ASYNCH_INITIALIZE bit in the   
// DBPROP_ROWSET_ASYNCH property before calling Execute().  
  
DBPROPSET CmdPropset[1];  
DBPROP CmdProperties[1];  
  
CmdPropset[0].rgProperties = CmdProperties;  
CmdPropset[0].cProperties = 1;  
CmdPropset[0].guidPropertySet = DBPROPSET_ROWSET;  
  
// Set asynch mode for command.  
CmdProperties[0].dwPropertyID = DBPROP_ROWSET_ASYNCH;  
CmdProperties[0].vValue.vt = VT_I4;  
CmdProperties[0].vValue.lVal = DBPROPVAL_ASYNCH_INITIALIZE;  
CmdProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;  
  
hr = pICommandProps->SetProperties(1, CmdPropset);  
  
hr = pICommand->Execute(  
   pUnkOuter,  
   IID_ISSAsynchStatus,  
   pParams,  
   pcRowsAffected,  
   (IUnknown**)&pISSAsynchStatus);  
  
if (hr == DB_S_ASYNCHRONOUS)  
{  
   // Do some work here...  
  
   hr = pISSAsynchStatus->WaitForAsynchCompletion(dwMilisecTimeOut);  
   if ( hr == S_OK)  
   {  
      hr = pISSAsynchStatus->QueryInterface(IID_IRowset, (void**)&pRowset);  
      pISSAsynchStatus->Release();  
   }  
}  

ISSAsynchStatus::WaitForAsynchCompletion espera pelo objeto de evento interno até que a operação de execução assíncrona seja concluída ou o valor dwMilisecTimeOut seja passado.

O exemplo seguinte mostra processamento assíncrono com múltiplos conjuntos de resultados:

DBPROP CmdProperties[1];  
  
// Set asynch mode for command.  
CmdProperties[0].dwPropertyID = DBPROP_ROWSET_ASYNCH;  
CmdProperties[0].vValue.vt = VT_I4;  
CmdProperties[0].vValue.lVal = DBPROPVAL_ASYNCH_INITIALIZE;  
  
hr = pICommand->Execute(  
   pUnkOuter,  
   IID_IMultipleResults,  
   pParams,  
   pcRowsAffected,  
   (IUnknown**)&pIMultipleResults);  
  
// Use GetResults for ISSAsynchStatus.  
hr = pIMultipleResults->GetResult(IID_ISSAsynchStatus, (void **) &pISSAsynchStatus);  
  
if (hr == DB_S_ASYNCHRONOUS)  
{  
   // Do some work here...  
  
   hr = pISSAsynchStatus->WaitForAsynchCompletion(dwMilisecTimeOut);  
   if (hr == S_OK)  
   {  
      hr = pISSAsynchStatus->QueryInterface(IID_IRowset, (void**)&pRowset);  
      pISSAsynchStatus->Release();  
   }  
}  

Para evitar bloqueios, o cliente pode verificar o estado de uma operação assíncrona em execução, como no seguinte exemplo:

// Set the DBPROPVAL_ASYNCH_INITIALIZE bit in the   
// DBPROP_ROWSET_ASYNCH property before calling Execute().  
hr = pICommand->Execute(  
   pUnkOuter,  
   IID_ISSAsynchStatus,  
   pParams,  
   pcRowsAffected,  
   (IUnknown**)&pISSAsynchStatus);   
  
if (hr == DB_S_ASYNCHRONOUS)  
{  
   do{  
      // Do some work...  
      hr = pISSAsynchStatus->GetStatus(DB_NULL_HCHAPTER, DBASYNCHOP_OPEN, NULL, NULL, &ulAsynchPhase, NULL);  
   }while (DBASYNCHPHASE_COMPLETE != ulAsynchPhase)  
   if SUCCEEDED(hr)  
   {  
      hr = pISSAsynchStatus->QueryInterface(IID_IRowset, (void**)&pRowset);  
   }  
   pIDBAsynchStatus->Release();  
}  

O exemplo seguinte demonstra como pode cancelar a operação assíncrona atualmente em execução:

// Set the DBPROPVAL_ASYNCH_INITIALIZE bit in the   
// DBPROP_ROWSET_ASYNCH property before calling Execute().  
hr = pICommand->Execute(  
   pUnkOuter,  
   IID_ISSAsynchStatus,  
   pParams,  
   pcRowsAffected,  
   (IUnknown**)&pISSAsynchStatus);  
  
if (hr == DB_S_ASYNCHRONOUS)  
{  
   // Do some work...  
   hr = pISSAsynchStatus->Abort(DB_NULL_HCHAPTER, DBASYNCHOP_OPEN);  
}  

Ver também

Driver OLE DB para Funcionalidades do SQL Server
Propriedades e Comportamentos do Conjunto de Linhas
ISSAsynchStatus (OLE DB)