Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
SQL Server permet aux applications d’effectuer des opérations de base de données asynchrones. Le traitement asynchrone permet aux méthodes de retourner immédiatement sans bloquer le thread appelant. Cela permet une grande partie de la puissance et de la flexibilité de la multithreading, sans exiger que le développeur crée explicitement des threads ou gère la synchronisation. Les applications demandent un traitement asynchrone lors de l’initialisation d’une connexion de base de données ou lors de l’initialisation du résultat de l’exécution d’une commande.
Ouverture et fermeture d’une connexion de base de données
Lors de l’utilisation du fournisseur OLE DB SQL Server Native Client, les applications conçues pour initialiser un objet source de données de manière asynchrone peuvent définir le DBPROPVAL_ASYNCH_INITIALIZE bit dans la propriété DBPROP_INIT_ASYNCH avant d’appeler IDBInitialize ::Initialize. Lorsque cette propriété est définie, le fournisseur retourne immédiatement à partir de l’appel à Initialiser avec S_OK, si l’opération s’est terminée immédiatement ou DB_S_ASYNCHRONOUS, si l’initialisation continue de façon asynchrone. Les applications peuvent interroger l’interface IDBAsynchStatus ou ISSAsynchStatussur l’objet de source de données, puis appeler IDBAsynchStatus ::GetStatus ouISSAsynchStatus ::WaitForAsynchCompletion pour obtenir l’état de l’initialisation.
En outre, la propriété SSPROP_ISSAsynchStatus a été ajoutée au jeu de propriétés DBPROPSET_SQLSERVERROWSET. Les fournisseurs qui prennent en charge l’interface ISSAsynchStatus doivent implémenter cette propriété avec la valeur de VARIANT_TRUE.
IDBAsynchStatus ::Abort ou ISSAsynchStatus ::Abort peut être appelé pour annuler l’appel Initialize asynchrone. Le consommateur doit demander explicitement l’initialisation de source de données asynchrone. Sinon, IDBInitialize ::Initialize ne retourne pas tant que l’objet source de données n’est pas entièrement initialisé.
Remarque
Les objets de source de données utilisés pour le regroupement de connexions ne peuvent pas appeler l’interface ISSAsynchStatus dans le fournisseur OLE DB SQL Server Native Client. L’interface ISSAsynchStatus n’est pas exposée pour les objets de source de données mis en pool.
Si une application force explicitement l’utilisation du moteur de curseur, IOpenRowset ::OpenRowset et IMultipleResults ::GetResult ne prend pas en charge le traitement asynchrone.
En outre, la dll proxy/stub de communication à distance (dans MDAC 2.8) ne peut pas appeler l’interface ISSAsynchStatus dans SQL Server Native Client. L’interface ISSAsynchStatus n’est pas exposée via la communication à distance.
Les composants de service ne prennent pas en charge ISSAsynchStatus.
Initialisation de l’ensemble de lignes et de l’exécution
Les applications conçues pour ouvrir de manière asynchrone le résultat de l’exécution d’une commande peuvent définir le bit DBPROPVAL_ASYNCH_INITIALIZE dans la propriété DBPROP_ROWSET_ASYNCH. Lorsque vous définissez ce bit avant d’appeler IDBInitialize ::Initialize, ICommand ::Execute, IOpenRowset ::OpenRowset ou IMultipleResults ::GetResult, l’argument riid doit être défini sur IID_IDBAsynchStatus, IID_ISSAsynchStatus ou IID_IUnknown.
La méthode retourne immédiatement avec S_OK si l’initialisation de l’ensemble de lignes se termine immédiatement ou avec DB_S_ASYNCHRONOUS si l’ensemble de lignes continue d’initialiser de façon asynchrone, avec ppRowset défini sur l’interface demandée sur l’ensemble de lignes. Pour le fournisseur OLE DB SQL Server Native Client, cette interface peut uniquement être IDBAsynchStatus ou ISSAsynchStatus. Tant que l’ensemble de lignes n’est pas entièrement initialisé, cette interface se comporte comme si elle était dans un état suspendu et appelait QueryInterface pour les interfaces autres que IID_IDBAsynchStatus ou IID_ISSAsynchStatus peut retourner E_NOINTERFACE. Sauf si le consommateur demande explicitement un traitement asynchrone, l’ensemble de lignes est initialisé de façon synchrone. Toutes les interfaces demandées sont disponibles lorsque IDBAsynchStaus ::GetStatus ou ISSAsynchStatus ::WaitForAsynchCompletion retourne l’indication que l’opération asynchrone est terminée. Cela ne signifie pas nécessairement que l’ensemble de lignes est entièrement rempli, mais qu’il est complet et entièrement fonctionnel.
Si la commande exécutée ne retourne pas d’ensemble de lignes, elle retourne toujours immédiatement avec un objet qui prend en charge IDBAsynchStatus.
Si vous devez obtenir plusieurs résultats à partir de l’exécution de commande asynchrone, vous devez :
Définissez le bit DBPROPVAL_ASYNCH_INITIALIZE de la propriété DBPROP_ROWSET_ASYNCH avant d’exécuter la commande.
Appelez ICommand ::Execute et demandez IMultipleResults.
Les interfaces IDBAsynchStatus et ISSAsynchStatus peuvent ensuite être obtenues en interrogeant l’interface de résultats multiples à l’aide de QueryInterface.
Lorsque la commande a terminé l’exécution, IMultipleResults peut être utilisé comme normal, à une exception de la casse synchrone : DB_S_ASYNCHRONOUS peut être retourné, auquel cas IDBAsynchStatus ou ISSAsynchStatus peut être utilisé pour déterminer quand l’opération est terminée.
Exemples
Dans l’exemple suivant, l’application appelle une méthode non bloquante, effectue un autre traitement, puis retourne pour traiter les résultats. ISSAsynchStatus ::WaitForAsynchCompletion attend sur l’objet d’événement interne jusqu’à ce que l’opération en cours d’exécution asynchrone soit terminée ou que la durée spécifiée par dwMilisecTimeOut soit passée.
// 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 attend sur l’objet d’événement interne jusqu’à ce que l’opération en cours d’exécution asynchrone soit effectuée ou que la valeur dwMilisecTimeOut soit passée.
L’exemple suivant montre le traitement asynchrone avec plusieurs jeux de résultats :
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();
}
}
Pour empêcher le blocage, le client peut vérifier l’état d’une opération asynchrone en cours d’exécution, comme dans l’exemple suivant :
// 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();
}
L’exemple suivant montre comment annuler l’opération asynchrone en cours d’exécution :
// 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);
}
Voir aussi
Fonctionnalités de SQL Server Native Client
Propriétés et comportements des ensembles de lignes
ISSAsynchStatus (OLE DB)