Realizar operaciones asincrónicas
Se aplica a: SQL Server Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW)
SQL Server permite a las aplicaciones realizar operaciones de base de datos asincrónicas. El procesamiento asincrónico permite a los métodos devolver resultados inmediatamente sin bloquear el subproceso que hace la llamada. Esto hace posible gran parte de la potencia y la flexibilidad del subprocesamiento múltiple, sin que el programador tenga que crear explícitamente subprocesos o administrar la sincronización. Las aplicaciones solicitan el procesamiento asincrónico al inicializar una conexión a la base de datos, o al inicializar el resultado de la ejecución de un comando.
Abrir y cerrar una conexión a la base de datos
Al usar el controlador OLE DB para SQL Server, las aplicaciones diseñadas para inicializar de forma asincrónica un objeto de origen de datos pueden establecer el bit DBPROPVAL_ASYNCH_INITIALIZE en la propiedad DBPROP_INIT_ASYNCH antes de llamar a IDBInitialize::Initialize. Cuando se establece esta propiedad, el resultado de la llamada del proveedor a Initialize es S_OK si la operación se ha completado inmediatamente, o bien DB_S_ASYNCHRONOUS si la inicialización continúa de forma asincrónica. Las aplicaciones pueden consultar la interfaz IDBAsynchStatus o ISSAsynchStatus en el objeto de origen de datos y llamar después a IDBAsynchStatus::GetStatus o ISSAsynchStatus::WaitForAsynchCompletion para obtener el estado de la inicialización.
Además, se ha agregado la propiedad SSPROP_ISSAsynchStatus al conjunto de propiedades DBPROPSET_SQLSERVERROWSET. Los proveedores que admiten la interfaz ISSAsynchStatus deben implementar esta propiedad con un valor de VARIANT_TRUE.
Se puede llamar a IDBAsynchStatus::Abort o ISSAsynchStatus::Abort para cancelar la llamada asincrónica a Initialize. El consumidor debe solicitar explícitamente la inicialización de origen de datos asincrónica. De lo contrario, IDBInitialize::Initialize no devuelve resultados hasta que se inicializa completamente el objeto de origen de datos.
Nota
Los objetos de origen de datos que se usan para agrupar conexiones no pueden llamar a la interfaz ISSAsynchStatus en el controlador OLE DB para SQL Server. La interfaz ISSAsynchStatus no se expone para objetos de origen de datos agrupados.
Si una aplicación obliga explícitamente a usar el motor de cursor, IOpenRowset::OpenRowset e IMultipleResults::GetResult no admitirán el procesamiento asincrónico.
Además, la dll de proxy/código auxiliar de comunicación remota (en MDAC 2.8) no puede llamar a la interfaz ISSAsynchStatus en el controlador OLE DB para SQL Server. La interfaz ISSAsynchStatus no se expone a través de la comunicación remota.
Los componentes de servicio no admiten ISSAsynchStatus.
Ejecución e inicialización de conjuntos de filas
Las aplicaciones diseñadas para abrir de forma asincrónica el resultado de la ejecución de un comando pueden establecer el bit DBPROPVAL_ASYNCH_INITIALIZE en la propiedad DBPROP_ROWSET_ASYNCH. Si se establece este bit antes de llamar a IDBInitialize::Initialize, ICommand::Execute, IOpenRowset::OpenRowset o IMultipleResults::GetResult, el argumento riid debe establecerse en IID_IDBAsynchStatus, IID_ISSAsynchStatus o IID_IUnknown.
El método devuelve inmediatamente S_OK si la inicialización del conjunto de filas se completa de forma inmediata, o DB_S_ASYNCHRONOUS si el conjunto de filas sigue inicializándose de forma asincrónica, con ppRowset establecido en la interfaz solicitada en el conjunto de filas. Para OLE DB Driver for SQL Server, esta inferfaz solo puede ser IDBAsynchStatus o ISSAsynchStatus. Hasta que el conjunto de filas está totalmente inicializado, esta interfaz se comporta como si estuviera en estado suspendido y las llamadas a QueryInterface para interfaces distintas de IID_IDBAsynchStatus o IID_ISSAsynchStatus pueden devolver E_NOINTERFACE. A menos que el consumidor solicite explícitamente el procesamiento asincrónico, el conjunto de filas se inicializa de forma sincrónica. Todos las interfaces solicitadas están disponibles cuando IDBAsynchStaus::GetStatus o ISSAsynchStatus::WaitForAsynchCompletion devuelven la indicación de que se ha completado la operación asincrónica. Esto no significa necesariamente que el conjunto de filas esté totalmente rellenado, pero está completo y es totalmente funcional.
Si el comando ejecutado no devuelve un conjunto de filas, sigue devolviendo inmediatamente un objeto que admite IDBAsynchStatus.
Si necesita recibir varios resultados de la ejecución de comandos asincrónica, debe hacer lo siguiente:
Establezca el bit DBPROPVAL_ASYNCH_INITIALIZE de la propiedad DBPROP_ROWSET_ASYNCH antes de ejecutar el comando.
Llame a ICommand::Execute y solicite IMultipleResults.
Las interfaces ISSAsynchStatus e IDBAsynchStatus se pueden obtener al consultar la interfaz de varios resultados mediante QueryInterface.
Una vez completada la ejecución del comando, IMultipleResults se puede usar de forma normal, con una excepción del caso sincrónico: se puede devolver DB_S_ASYNCHRONOUS, en cuyo caso se puede usar IDBAsynchStatus o ISSAsynchStatus para determinar cuándo se ha completado la operación.
Ejemplos
En el ejemplo siguiente, la aplicación llama a un método de no bloqueo, realiza algún otro procesamiento y, después, vuelve a procesar los resultados. ISSAsynchStatus::WaitForAsynchCompletion espera en el objeto de evento interno hasta que se completa la operación de ejecución asincrónica o transcurre el tiempo especificado por dwMilisecTimeOut.
// 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 en el objeto de evento interno hasta que se completa la operación de ejecución asincrónica o transcurre el valor de dwMilisecTimeOut.
En el ejemplo siguiente se muestra el procesamiento asincrónico con varios 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 bloqueos, el cliente puede comprobar el estado de una operación asincrónica en ejecución, como en el ejemplo siguiente:
// 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();
}
El ejemplo siguiente muestra cómo puede cancelar la operación asincrónica que se está ejecutando en este momento:
// 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);
}
Consulte también
Controlador OLE DB para las características de SQL Server
Propiedades y comportamientos de conjuntos de filas
ISSAsynchStatus (OLE DB)