Delen via


Asynchrone Uitvoering (Pollingmethode)

Vóór ODBC 3.8 en de Windows 7 SDK waren asynchrone bewerkingen alleen toegestaan voor instructiefuncties. Zie voor meer informatie het uitvoeren van instructiebewerkingen asynchroon, later in dit onderwerp.

ODBC 3.8 in de Windows 7 SDK heeft asynchrone uitvoering geïntroduceerd voor verbindingsgerelateerde bewerkingen. Zie de sectie Verbindingsbewerkingen asynchroon uitvoeren verderop in dit onderwerp voor meer informatie.

In de Windows 7 SDK, voor asynchrone opdracht- of verbindingsbewerkingen, kon een toepassing bepalen dat de asynchrone bewerking was voltooid door de polling-methode. Vanaf de Windows 8 SDK kunt u bepalen dat een asynchrone bewerking is voltooid met behulp van de meldingsmethode. Zie Asynchrone uitvoering (meldingsmethode) voor meer informatie.

Standaard voeren stuurprogramma's ODBC-functies synchroon uit; Dat wil gezegd, de toepassing roept een functie aan en het stuurprogramma retourneert geen controle naar de toepassing totdat het uitvoeren van de functie is voltooid. Sommige functies kunnen echter asynchroon worden uitgevoerd; Dat wil gezegd, de toepassing roept de functie aan en het stuurprogramma, na minimale verwerking, retourneert het besturingselement naar de toepassing. De toepassing kan vervolgens andere functies aanroepen terwijl de eerste functie nog steeds wordt uitgevoerd.

Asynchrone uitvoering wordt ondersteund voor de meeste functies die grotendeels worden uitgevoerd op de gegevensbron, zoals de functies voor het tot stand brengen van verbindingen, het voorbereiden en uitvoeren van SQL-instructies, het ophalen van metagegevens, het ophalen van gegevens en doorvoertransacties. Dit is het handigst wanneer het lang duurt voordat de taak wordt uitgevoerd op de gegevensbron, zoals een aanmeldingsproces of een complexe query voor een grote database.

Wanneer de toepassing een functie uitvoert met een instructie of verbinding die is ingeschakeld voor asynchrone verwerking, voert het stuurprogramma een minimale hoeveelheid verwerking uit (zoals het controleren van argumenten op fouten), handelt de verwerking over aan de gegevensbron en geeft de besturing terug aan de toepassing met de SQL_STILL_EXECUTING retourcode. De toepassing voert vervolgens andere taken uit. Om te bepalen wanneer de asynchrone functie is voltooid, pollt de toepassing het stuurprogramma regelmatig door de functie aan te roepen met dezelfde argumenten als die die oorspronkelijk is gebruikt. Als de functie nog steeds wordt uitgevoerd, wordt SQL_STILL_EXECUTING geretourneerd; als het is voltooid met uitvoeren, wordt de code geretourneerd die zou zijn geretourneerd als deze synchroon is uitgevoerd, zoals SQL_SUCCESS, SQL_ERROR of SQL_NEED_DATA.

Of een functie synchroon of asynchroon wordt uitgevoerd, is stuurprogrammaspecifiek. Stel dat de metagegevens van de resultatenset in de cache worden opgeslagen in het stuurprogramma. In dit geval kost het weinig tijd om SQLDescribeCol uit te voeren en moet het stuurprogramma gewoon de functie uitvoeren in plaats van de uitvoering kunstmatig uit te stellen. Als het stuurprogramma daarentegen de metagegevens uit de gegevensbron moet ophalen, moet het de besturing naar de toepassing retourneren terwijl het dit doet. Daarom moet de toepassing een andere retourcode dan SQL_STILL_EXECUTING kunnen verwerken wanneer deze voor het eerst een functie asynchroon uitvoert.

Instructies voor statementbewerkingen asynchroon uitvoeren

De volgende statementfuncties werken op een gegevensbron en kunnen asynchroon worden uitgevoerd.

De uitvoering van asynchrone instructies wordt beheerd per instructie of per verbinding, afhankelijk van de gegevensbron. Dat wil zeggen dat de toepassing niet aangeeft dat een bepaalde functie asynchroon moet worden uitgevoerd, maar dat een functie die wordt uitgevoerd op een bepaalde instructie asynchroon moet worden uitgevoerd. Om erachter te komen welke wordt ondersteund, roept een toepassing SQLGetInfo aan met een optie van SQL_ASYNC_MODE. SQL_AM_CONNECTION wordt geretourneerd als asynchrone uitvoering op verbindingsniveau (voor een instructiehandgreep) wordt ondersteund; SQL_AM_STATEMENT als asynchrone uitvoering op instructieniveau wordt ondersteund.

Als u wilt opgeven dat functies die met een bepaalde instructie worden uitgevoerd asynchroon moeten worden uitgevoerd, roept de toepassing SQLSetStmtAttr aan met het kenmerk SQL_ATTR_ASYNC_ENABLE en stelt deze in op SQL_ASYNC_ENABLE_ON. Als asynchrone verwerking op verbindingsniveau wordt ondersteund, is het kenmerk SQL_ATTR_ASYNC_ENABLE van de instructie alleen-lezen en is de waarde ervan dezelfde als die van het verbindingskenmerk van de verbinding waarop de instructie is toegewezen. Het is afhankelijk van de driver of de waarde van het kenmerk van de instructie wordt ingesteld tijdens of na de toewijzing van de instructie. Als u dit probeert in te stellen, worden SQL_ERROR en SQLSTATE HYC00 geretourneerd (optionele functie niet geïmplementeerd).

Om op te geven dat functies die met een bepaalde verbinding worden uitgevoerd asynchroon moeten worden uitgevoerd, roept de toepassing SQLSetConnectAttr aan met het SQL_ATTR_ASYNC_ENABLE kenmerk en stelt deze in op SQL_ASYNC_ENABLE_ON. Alle toekomstige instructie-handles die zijn toegewezen aan de connectie, worden ingeschakeld voor asynchrone uitvoering; het is door het stuurprogramma gedefinieerd of bestaande instructie-handles door deze actie worden ingeschakeld. Als SQL_ATTR_ASYNC_ENABLE is ingesteld op SQL_ASYNC_ENABLE_OFF, bevinden alle instructies voor de verbinding zich in de synchrone modus. Er wordt een fout geretourneerd als asynchrone uitvoering is ingeschakeld terwijl er een actieve instructie op de verbinding is.

Om het maximum aantal actieve gelijktijdige instructies te bepalen in de asynchrone modus die het stuurprogramma kan ondersteunen voor een bepaalde verbinding, roept de toepassing SQLGetInfo aan met de optie SQL_MAX_ASYNC_CONCURRENT_STATEMENTS.

De volgende code laat zien hoe het polling-model werkt:

SQLHSTMT  hstmt1;  
SQLRETURN rc;  
  
// Specify that the statement is to be executed asynchronously.  
SQLSetStmtAttr(hstmt1, SQL_ATTR_ASYNC_ENABLE, SQL_ASYNC_ENABLE_ON, 0);  
  
// Execute a SELECT statement asynchronously.  
while ((rc=SQLExecDirect(hstmt1,"SELECT * FROM Orders",SQL_NTS))==SQL_STILL_EXECUTING) {  
   // While the statement is still executing, do something else.  
   // Do not use hstmt1, because it is being used asynchronously.  
}  
  
// When the statement has finished executing, retrieve the results.  

Terwijl een functie asynchroon wordt uitgevoerd, kan de toepassing functies aanroepen op andere instructies. De toepassing kan ook functies aanroepen voor elke verbinding, behalve de functie die is gekoppeld aan de asynchrone instructie. Maar de toepassing kan alleen de oorspronkelijke functie aanroepen en de volgende functies (met de instructiegreep of de bijbehorende verbinding, omgevingsgreep), nadat een instructiebewerking SQL_STILL_EXECUTING retourneert:

Als de toepassing een andere functie aanroept met de asynchrone instructie of met de verbinding die aan die instructie is gekoppeld, retourneert de functie bijvoorbeeld SQLSTATE HY010 (functiereeksfout).

SQLHDBC       hdbc1, hdbc2;  
SQLHSTMT      hstmt1, hstmt2, hstmt3;  
SQLCHAR *     SQLStatement = "SELECT * FROM Orders";  
SQLUINTEGER   InfoValue;  
SQLRETURN     rc;  
  
SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);  
SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt2);  
SQLAllocHandle(SQL_HANDLE_STMT, hdbc2, &hstmt3);  
  
// Specify that hstmt1 is to be executed asynchronously.  
SQLSetStmtAttr(hstmt1, SQL_ATTR_ASYNC_ENABLE, SQL_ASYNC_ENABLE_ON, 0);  
  
// Execute hstmt1 asynchronously.  
while ((rc = SQLExecDirect(hstmt1, SQLStatement, SQL_NTS)) == SQL_STILL_EXECUTING) {  
   // The following calls return HY010 because the previous call to  
   // SQLExecDirect is still executing asynchronously on hstmt1. The  
   // first call uses hstmt1 and the second call uses hdbc1, on which  
   // hstmt1 is allocated.  
   SQLExecDirect(hstmt1, SQLStatement, SQL_NTS);   // Error!  
   SQLGetInfo(hdbc1, SQL_UNION, (SQLPOINTER) &InfoValue, 0, NULL);   // Error!  
  
   // The following calls do not return errors. They use a statement  
   // handle other than hstmt1 or a connection handle other than hdbc1.  
   SQLExecDirect(hstmt2, SQLStatement, SQL_NTS);   // OK  
   SQLTables(hstmt3, NULL, 0, NULL, 0, NULL, 0, NULL, 0);   // OK  
   SQLGetInfo(hdbc2, SQL_UNION, (SQLPOINTER) &InfoValue, 0, NULL);   // OK  
}  

Wanneer een toepassing een functie aanroept om te bepalen of deze nog steeds asynchroon wordt uitgevoerd, moet deze de oorspronkelijke instructiehandgreep gebruiken. Dit komt doordat asynchrone uitvoering per instructie wordt bijgehouden. De applicatie moet ook geldige waarden opgeven voor de andere argumenten - de oorspronkelijke argumenten zijn voldoende - om foutcontroles in de Driver Manager te doorstaan. Nadat het stuurprogramma echter heeft gecontroleerd of de statement handle wordt uitgevoerd en heeft vastgesteld dat de instructie asynchroon uitvoert, worden alle andere argumenten genegeerd.

Hoewel een functie asynchroon wordt uitgevoerd, dat wil zeggen, nadat deze SQL_STILL_EXECUTING heeft geretourneerd en voordat deze een andere code retourneert, kan de toepassing deze annuleren door SQLCancel of SQLCancelHandle aan te roepen met dezelfde instructiegreep. Het annuleren van de uitvoering van de functie is niet gegarandeerd. De functie is bijvoorbeeld al voltooid. Bovendien geeft de code die wordt geretourneerd door SQLCancel of SQLCancelHandle alleen aan of de poging om de functie te annuleren is geslaagd, niet of de functie daadwerkelijk is geannuleerd. Om te bepalen of de functie is geannuleerd, roept de toepassing de functie opnieuw aan. Als de functie is geannuleerd, retourneert deze SQL_ERROR en SQLSTATE HY008 (Bewerking geannuleerd). Als de functie niet is geannuleerd, retourneert deze een andere code, zoals SQL_SUCCESS, SQL_STILL_EXECUTING of SQL_ERROR met een andere SQLSTATE.

Als u asynchrone uitvoering van een bepaalde instructie wilt uitschakelen wanneer het stuurprogramma asynchrone verwerking op instructieniveau ondersteunt, roept de toepassing SQLSetStmtAttr aan met het kenmerk SQL_ATTR_ASYNC_ENABLE en stelt deze in op SQL_ASYNC_ENABLE_OFF. Als het stuurprogramma asynchrone verwerking op verbindingsniveau ondersteunt, roept de toepassing SQLSetConnectAttr aan om SQL_ATTR_ASYNC_ENABLE in te stellen op SQL_ASYNC_ENABLE_OFF, waardoor asynchrone uitvoering van alle instructies op de verbinding wordt uitgeschakeld.

De toepassing moet diagnostische records verwerken in de herhalende lus van de oorspronkelijke functie. Als SQLGetDiagField of SQLGetDiagRec wordt aangeroepen wanneer een asynchrone functie wordt uitgevoerd, wordt de huidige lijst met diagnostische records geretourneerd. Telkens wanneer de oorspronkelijke functie-aanroep wordt herhaald, worden eerdere diagnostische records gewist.

Verbindingsbewerkingen asynchroon uitvoeren

Vóór ODBC 3.8 was asynchrone uitvoering toegestaan voor instructiegerelateerde bewerkingen, zoals voorbereiden, uitvoeren en ophalen, evenals voor bewerkingen met catalogusmetagegevens. Vanaf ODBC 3.8 is asynchrone uitvoering ook mogelijk voor verbindingsgerelateerde bewerkingen, zoals verbinding maken, verbinding verbreken, doorvoeren en terugdraaien.

Zie Wat is er nieuw in ODBC 3.8 voor meer informatie over ODBC 3.8.

Het asynchroon uitvoeren van verbindingsbewerkingen is handig in de volgende scenario's:

  • Wanneer een klein aantal threads een groot aantal apparaten beheert met zeer hoge gegevenssnelheden. Om de reactiesnelheid en schaalbaarheid te maximaliseren, is het wenselijk dat alle bewerkingen asynchroon zijn.

  • Wanneer u databasebewerkingen over meerdere verbindingen wilt overlappen om verstreken overdrachtstijden te verminderen.

  • Efficiënte asynchrone ODBC-aanroepen en de mogelijkheid om verbindingsbewerkingen te annuleren, stellen een toepassing in staat om een trage bewerking te annuleren zonder te hoeven wachten op time-outs.

De volgende functies, die op verbindingsingangen werken, kunnen nu asynchroon worden uitgevoerd:

Om te bepalen of een stuurprogramma asynchrone bewerkingen op deze functies ondersteunt, roept een toepassing SQLGetInfo aan met SQL_ASYNC_DBC_FUNCTIONS. SQL_ASYNC_DBC_CAPABLE wordt geretourneerd als asynchrone bewerkingen worden ondersteund. SQL_ASYNC_DBC_NOT_CAPABLE wordt geretourneerd als asynchrone bewerkingen niet worden ondersteund.

Om op te geven dat functies die met een bepaalde verbinding worden uitgevoerd asynchroon moeten worden uitgevoerd, roept de toepassing SQLSetConnectAttr aan en stelt het kenmerk SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE in op SQL_ASYNC_DBC_ENABLE_ON. Het instellen van een verbindingskenmerk voordat een verbinding tot stand wordt gebracht, wordt altijd synchroon uitgevoerd. Bovendien wordt de bewerking die het verbindingskenmerk instelt SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE met SQLSetConnectAttr altijd synchroon uitgevoerd.

Een toepassing kan asynchrone bewerking inschakelen voordat er verbinding wordt gemaakt. Omdat Driver Manager niet kan bepalen welk stuurprogramma moet worden gebruikt voordat er verbinding wordt gemaakt, retourneert Driver Manager altijd succes in SQLSetConnectAttr. Er kan echter geen verbinding worden gemaakt als het ODBC-stuurprogramma geen asynchrone bewerkingen ondersteunt.

Over het algemeen kan er maximaal één asynchroon uitgevoerde functie zijn gekoppeld aan een bepaalde verbindingsgreep of instructiegreep. Een verbindingsgreep kan echter meer dan één bijbehorende statementhandle hebben. Als er geen asynchrone bewerking wordt uitgevoerd op de connection handle, kan een bijbehorende statement handle een asynchrone bewerking uitvoeren. Op dezelfde manier kunt u een asynchrone bewerking uitvoeren op een verbindingshandvat als er geen asynchrone bewerkingen worden uitgevoerd op een bijbehorend instructiehandvat. Een poging om een asynchrone bewerking uit te voeren met behulp van een ingang die momenteel een asynchrone bewerking uitvoert, retourneert HY010, 'Functiereeksfout'.

Als een verbindingsbewerking SQL_STILL_EXECUTING retourneert, kan een toepassing alleen de oorspronkelijke functie aanroepen en de volgende functies voor die verbindingsgreep:

  • SQLCancelHandle (op de verbindingsgreep)

  • SQLGetDiagField

  • SQLGetDiagRec

  • SQLAllocHandle (ENV/DBC toewijzen)

  • SQLAllocHandleStd (ENV/DBC toewijzen)

  • SQLGetEnvAttr

  • SQLGetConnectAttr

  • SQLDataSources

  • SQLDrivers

  • SQLGetInfo

  • SQLGetFunctions

De toepassing moet diagnostische records verwerken in de herhalende lus van de oorspronkelijke functie. Als SQLGetDiagField of SQLGetDiagRec wordt aangeroepen wanneer een asynchrone functie wordt uitgevoerd, wordt de huidige lijst met diagnostische records geretourneerd. Telkens wanneer de oorspronkelijke functie-aanroep wordt herhaald, worden eerdere diagnostische records gewist.

Als een verbinding asynchroon wordt geopend of gesloten, is de bewerking voltooid wanneer de toepassing SQL_SUCCESS of SQL_SUCCESS_WITH_INFO ontvangt in de oorspronkelijke functieaanroep.

Er is een nieuwe functie toegevoegd aan ODBC 3.8, SQLCancelHandle. Deze functie annuleert de zes verbindingsfuncties (SQLBrowseConnect, SQLConnect, SQLDisconnect, SQLDriverConnect, SQLEndTran en SQLSetConnectAttr). Een toepassing moet SQLGetFunctions aanroepen om te bepalen of het stuurprogramma SQLCancelHandle ondersteunt. Net als bij SQLCancel betekent het niet dat de bewerking is geannuleerd als SQLCancelHandle een succes retourneert. Een toepassing moet de oorspronkelijke functie opnieuw aanroepen om te bepalen of de bewerking is geannuleerd. Met SQLCancelHandle kunt u asynchrone bewerkingen op verbindingsgrepen of instructiegrepen annuleren. Het gebruik van SQLCancelHandle om een bewerking op een instructiegreep te annuleren, is hetzelfde als het aanroepen van SQLCancel.

Het is niet nodig om gelijktijdig zowel SQLCancelHandle - als asynchrone verbindingsbewerkingen te ondersteunen. Een stuurprogramma kan asynchrone verbindingsbewerkingen ondersteunen, maar niet SQLCancelHandle, of omgekeerd.

Asynchrone verbindingsbewerkingen en SQLCancelHandle kunnen ook worden gebruikt door ODBC 3.x- en ODBC 2.x-toepassingen met een ODBC 3.8-stuurprogramma en ODBC 3.8-stuurprogrammabeheer. Zie Compatibiliteitsmatrix voor informatie over het inschakelen van een oudere toepassing voor het gebruik van nieuwe functies in latere ODBC-versie.

Groepsgewijze verbindingen

Wanneer groepsgewijze verbindingen zijn ingeschakeld, worden asynchrone bewerkingen slechts minimaal ondersteund voor het tot stand brengen van een verbinding (met SQLConnect en SQLDriverConnect) en het sluiten van een verbinding met SQLDisconnect. Maar een toepassing moet de retourwaarde van de SQL_STILL_EXECUTING nog steeds kunnen verwerken vanuit SQLConnect, SQLDriverConnect en SQLDisconnect.

Wanneer groepsgewijze verbindingen is ingeschakeld, worden SQLEndTran en SQLSetConnectAttr ondersteund voor asynchrone bewerkingen.

Voorbeelden

Eén. Asynchrone uitvoering van verbindingsfuncties inschakelen

In het volgende voorbeeld ziet u hoe u SQLSetConnectAttr gebruikt om asynchrone uitvoering in te schakelen voor verbindingsgerelateerde functies.

BOOL AsyncConnect (SQLHANDLE hdbc)   
{  
   SQLRETURN r;  
   SQLHANDLE hdbc;  
  
   // Enable asynchronous execution of connection functions.  
   // This must be executed synchronously, that is r != SQL_STILL_EXECUTING  
   r = SQLSetConnectAttr(  
         hdbc,   
         SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE,  
         reinterpret_cast<SQLPOINTER> (SQL_ASYNC_DBC_ENABLE_ON),  
         0);  
   if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)   
   {  
      return FALSE;  
   }  
  
   TCHAR szConnStrIn[256] = _T("DSN=AsyncDemo");  
  
   r = SQLDriverConnect(hdbc, NULL, (SQLTCHAR *) szConnStrIn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);  
  
   if (r == SQL_ERROR)   
   {  
      // Use SQLGetDiagRec to process the error.  
      // If SQLState is HY114, the driver does not support asynchronous execution.  
      return FALSE;  
   }  
  
   while (r == SQL_STILL_EXECUTING)   
   {  
      // Do something else.  
  
      // Check for completion, with the same set of arguments.  
      r = SQLDriverConnect(hdbc, NULL, (SQLTCHAR *) szConnStrIn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);  
   }  
  
   if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)   
   {  
      return FALSE;  
   }  
  
   return TRUE;  
}  
  

B. Asynchrone doorvoerbewerkingen

In dit voorbeeld ziet u asynchrone doorvoerbewerkingen. Terugdraaibewerkingen kunnen ook op deze manier worden uitgevoerd.

BOOL AsyncCommit ()   
{  
   SQLRETURN r;   
  
   // Assume that SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE is SQL_ASYNC_DBC_ENABLE_ON.  
  
   r = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);  
   while (r == SQL_STILL_EXECUTING)   
   {  
      // Do something else.  
  
      // Check for completion with the same set of arguments.  
      r = SQLEndTran(SQL_HANDLE_DBC, hdbc, SQL_COMMIT);  
   }  
  
   if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO)   
   {  
      return FALSE;  
   }  
   return TRUE;  
}  

Zie ook

ODBC-instructies uitvoeren