Sdílet prostřednictvím


Asynchronní spuštění (metoda dotazování)

Před rozhraním ODBC 3.8 a sadou Windows 7 SDK byly asynchronní operace povoleny pouze u funkcí příkazů. Další informace naleznete v části Provádění operací příkazů asynchronně, dále v tomto tématu.

Rozhraní ODBC 3.8 v sadě Windows 7 SDK zavedlo asynchronní spouštění operací souvisejících s připojením. Další informace naleznete v části Provádění operací připojení asynchronně , dále v tomto tématu.

V sadě Windows 7 SDK určila aplikace u asynchronních příkazů nebo operací připojení dokončení asynchronní operace pomocí metody průzkumu. Počínaje sadou Windows 8 SDK můžete určit, že asynchronní operace je dokončena pomocí metody oznámení. Další informace naleznete v tématu Asynchronní spuštění (metoda oznámení).

Ve výchozím nastavení ovladače spouští funkce ODBC synchronně; to znamená, že aplikace volá funkci a ovladač nevrátí řízení do aplikace, dokud nedokončí provádění funkce. Některé funkce však lze spouštět asynchronně; to znamená, že aplikace volá funkci a ovladač po minimálním zpracování vrátí řízení do aplikace. Aplikace pak může volat jiné funkce, zatímco první funkce se stále spouští.

Asynchronní spouštění je podporováno pro většinu funkcí, které jsou z velké části spouštěny ve zdroji dat, jako jsou funkce pro navázání připojení, příprava a spouštění příkazů SQL, načítání metadat, načítání dat a potvrzení transakcí. Nejužitečnější je, když úloha spuštěná ve zdroji dat trvá dlouhou dobu, například proces přihlášení nebo složitý dotaz na velkou databázi.

Když aplikace spustí funkci s příkazem nebo připojením, které je povoleno pro asynchronní zpracování, ovladač provede minimální množství zpracování (například kontrolu argumentů na chyby), předá zpracování zdroji dat a vrátí řízení do aplikace s návratovým kódem SQL_STILL_EXECUTING. Aplikace pak provede další úlohy. Pokud chcete zjistit, kdy asynchronní funkce skončí, aplikace dotazuje ovladač v pravidelných intervalech voláním funkce se stejnými argumenty jako původně použitá. Pokud se funkce stále spouští, vrátí SQL_STILL_EXECUTING; Pokud se dokončilo provádění, vrátí kód, který by vrátil, pokud by se spustil synchronně, například SQL_SUCCESS, SQL_ERROR nebo SQL_NEED_DATA.

Bez ohledu na to, jestli se funkce spouští synchronně nebo asynchronně, je specifická pro ovladač. Předpokládejme například, že metadata sady výsledků jsou uložena v mezipaměti ovladače. V tomto případě trvá spuštění SQLDescribeCol velmi málo času a ovladač by měl jednoduše spustit funkci místo umělého zpoždění provádění. Na druhou stranu, pokud ovladač potřebuje načíst metadata ze zdroje dat, měl by vrátit řízení do aplikace, zatímco to dělá. Aplikace proto musí být schopná zpracovat jiný návratový kód než SQL_STILL_EXECUTING při prvním spuštění funkce asynchronně.

Asynchronní vykonávání operací s SQL příkazy

Následující funkce příkazů pracují se zdrojem dat a můžou se spouštět asynchronně:

Asynchronní provádění příkazů je řízeno buď pro jednotlivé příkazy, nebo na úrovni připojení v závislosti na zdroji dat. To znamená, že aplikace neurčí, že konkrétní funkce se má spouštět asynchronně, ale že každá funkce spuštěná u konkrétního příkazu se má spouštět asynchronně. Pokud chcete zjistit, který z nich je podporovaný, aplikace volá SQLGetInfo s možností SQL_ASYNC_MODE. SQL_AM_CONNECTION se vrátí, pokud je podporováno asynchronní spouštění na úrovni připojení (pro popisovač příkazu); SQL_AM_STATEMENT se vrátí, pokud je podporováno asynchronní spouštění na úrovni příkazů.

Chcete-li určit, že funkce spouštěné pomocí konkrétního příkazu se mají spouštět asynchronně, aplikace volá SQLSetStmtAttr s atributem SQL_ATTR_ASYNC_ENABLE a nastaví je na SQL_ASYNC_ENABLE_ON. Pokud se podporuje asynchronní zpracování na úrovni připojení, atribut příkazu SQL_ATTR_ASYNC_ENABLE je jen pro čtení a jeho hodnota je stejná jako atribut připojení připojení, na kterém byl příkaz přidělen. Zda je hodnota atributu příkazu nastavena při přidělení příkazu nebo později, závisí na konkrétním ovladači. Pokus o nastavení vrátí SQL_ERROR a SQLSTATE HYC00 (volitelná funkce není implementována).

Chcete-li určit, že funkce spuštěné s konkrétním připojením se mají spouštět asynchronně, aplikace volá SQLSetConnectAttr s atributem SQL_ATTR_ASYNC_ENABLE a nastaví je na SQL_ASYNC_ENABLE_ON. Všechny budoucí obslužné rutiny příkazů přidělené na připojení budou povoleny pro asynchronní spuštění; je na ovladači, zda tato akce povolí i stávající obslužné rutiny příkazů. Pokud je SQL_ATTR_ASYNC_ENABLE nastavená na SQL_ASYNC_ENABLE_OFF, všechny příkazy připojení jsou v synchronním režimu. Pokud je povoleno asynchronní spouštění při aktivním výrazu v připojení, vrátí se chyba.

Chcete-li určit maximální počet aktivních souběžných příkazů v asynchronním režimu, který ovladač může podporovat v daném připojení, aplikace volá SQLGetInfo s možností SQL_MAX_ASYNC_CONCURRENT_STATEMENTS.

Následující kód ukazuje, jak model dotazování funguje:

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.  

Zatímco se funkce spouští asynchronně, aplikace může volat funkce u všech dalších příkazů. Aplikace může také volat funkce na jakémkoli připojení, s výjimkou toho přidruženého k asynchronnímu příkazu. Aplikace ale může volat pouze původní funkci a následující funkce (s popisovačem příkazu nebo jeho přidruženým připojením, popisovačem prostředí) po operaci příkazu vrátí SQL_STILL_EXECUTING:

Pokud aplikace volá jakoukoli jinou funkci s asynchronním příkazem nebo s připojením přidruženým k tomuto příkazu, funkce vrátí SQLSTATE HY010 (chyba sekvence funkcí), například.

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  
}  

Když aplikace zavolá funkci, která určí, jestli se stále spouští asynchronně, musí použít původní popisovač příkazu. Důvodem je to, že asynchronní spouštění se sleduje na základě jednotlivých příkazů. Aplikace musí také zadat platné hodnoty pro ostatní argumenty – původní argumenty poslouží – aby prošly kontrolou chyb ve Správci ovladačů. Jakmile však ovladač zkontroluje popisovač příkazu a určí, že příkaz se spouští asynchronně, ignoruje všechny ostatní argumenty.

Zatímco se funkce spouští asynchronně – tj. po vrácení SQL_STILL_EXECUTING a před vrácením jiného kódu – aplikace ji může zrušit voláním SQLCancel nebo SQLCancelHandle se stejným popisovačem příkazu. Není zaručeno, že to zruší vykonávání funkce. Například funkce už možná skončila. Kromě toho kód vrácený sqlCancel nebo SQLCancelHandle pouze indikuje, zda pokus o zrušení funkce byl úspěšný, ne zda skutečně zrušil funkci. Pokud chcete zjistit, jestli byla funkce zrušena, aplikace tuto funkci znovu zavolá. Pokud byla funkce zrušena, vrátí SQL_ERROR a SQLSTATE HY008 (operace byla zrušena). Pokud funkce nebyla zrušena, vrátí jiný kód, například SQL_SUCCESS, SQL_STILL_EXECUTING nebo SQL_ERROR s jiným kódem SQLSTATE.

Chcete-li zakázat asynchronní spuštění konkrétního příkazu, pokud ovladač podporuje asynchronní zpracování na úrovni příkazů, aplikace volá SQLSetStmtAttr s atributem SQL_ATTR_ASYNC_ENABLE a nastaví ho na SQL_ASYNC_ENABLE_OFF. Pokud ovladač podporuje asynchronní zpracování na úrovni připojení, aplikace volá SQLSetConnectAttr k nastavení SQL_ATTR_ASYNC_ENABLE na SQL_ASYNC_ENABLE_OFF, což zakáže asynchronní spouštění všech příkazů v připojení.

Aplikace by měla zpracovávat diagnostické záznamy ve smyčce opakování původní funkce. Pokud je při spuštění asynchronní funkce volána funkce SQLGetDiagField nebo SQLGetDiagRec , vrátí aktuální seznam diagnostických záznamů. Vymaže předchozí diagnostické záznamy pokaždé, když se opakuje volání původní funkce.

Asynchronní provádění operací připojení

Před rozhraním ODBC 3.8 bylo povolené asynchronní spouštění pro operace související s příkazy, jako jsou příprava, spuštění a načítání, a také operace s metadaty katalogu. Počínaje rozhraním ODBC 3.8 je také možné asynchronní spouštění pro operace související s připojením, jako jsou připojení, odpojení, potvrzení a vrácení zpět.

Další informace o rozhraní ODBC 3.8 naleznete v tématu Co je nového v rozhraní ODBC 3.8.

Asynchronní provádění operací připojení je užitečné v následujících scénářích:

  • Když malý počet vláken spravuje velký počet zařízení s velmi vysokou rychlostí dat. K maximalizaci rychlosti odezvy a škálovatelnosti je žádoucí, aby všechny operace byly asynchronní.

  • Pokud chcete překrývat databázové operace s více připojeními, abyste snížili dobu uplynulého přenosu.

  • Efektivní asynchronní volání ODBC a možnost zrušit operace připojení umožňují aplikaci povolit uživateli zrušit jakoukoli pomalou operaci bez nutnosti čekat na vypršení časových limitů.

Následující funkce, které pracují s popisovači připojení, se teď dají spustit asynchronně:

Chcete-li zjistit, zda ovladač podporuje asynchronní operace s těmito funkcemi, aplikace volá SQLGetInfo s SQL_ASYNC_DBC_FUNCTIONS. SQL_ASYNC_DBC_CAPABLE se vrátí, pokud jsou podporovány asynchronní operace. SQL_ASYNC_DBC_NOT_CAPABLE se vrátí, pokud nejsou podporovány asynchronní operace.

Chcete-li určit, že funkce spuštěné s konkrétním připojením se mají spouštět asynchronně, aplikace volá SQLSetConnectAttr a nastaví atribut SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE na SQL_ASYNC_DBC_ENABLE_ON. Nastavení atributu připojení před navázáním připojení se vždy provede synchronně. Také operace nastavení atributu připojení SQL_ATTR_ASYNC_DBC_FUNCTIONS_ENABLE pomocí SQLSetConnectAttr vždy provádí synchronně.

Aplikace může před vytvořením připojení povolit asynchronní operaci. Vzhledem k tomu, že Správce ovladačů nemůže určit, který ovladač se má použít před připojením, správce ovladačů vždy vrátí úspěch v SQLSetConnectAttr. Pokud však ovladač ODBC nepodporuje asynchronní operace, může selhat připojení.

Obecně platí, že k určitému popisovači připojení nebo popisovači příkazu může být přidružena nanejvýš jedna funkce spuštěná asynchronně. Popisovač připojení ale může mít více než jeden přidružený popisovač SQL příkazu. Pokud na popisovači připojení není spuštěna žádná asynchronní operace, může přidružený popisovač příkazu spustit asynchronní operaci. Podobně můžete mít asynchronní operaci na popisovači připojení, pokud na žádném přidruženém popisovači příkazu neprobíhá žádná asynchronní operace. Pokus o provedení asynchronní operace pomocí popisovače, který právě spouští asynchronní operaci, vrátí HY010, "Chyba sekvence funkce".

Pokud operace připojení vrátí SQL_STILL_EXECUTING, může aplikace volat pouze původní funkci a následující funkce pro tento popisovač připojení:

  • SQLCancelHandle (na handlu připojení)

  • Sqlgetdiagfield

  • SQLGetDiagRec

  • SQLAllocHandle (přidělování ENV/DBC)

  • SQLAllocHandleStd (přidělování ENV/DBC)

  • SQLGetEnvAttr

  • SQLGetConnectAttr

  • SQLDataSources

  • SQLDrivers

  • Sqlgetinfo

  • FUNKCE SQLGetFunctions

Aplikace by měla zpracovávat diagnostické záznamy ve smyčce opakování původní funkce. Pokud je při spuštění asynchronní funkce volána funkce SQLGetDiagField nebo SQLGetDiagRec, vrátí aktuální seznam diagnostických záznamů. Při každém opakování původního volání funkce se vymažou předchozí diagnostické záznamy.

Pokud je připojení otevřeno nebo uzavřeno asynchronně, je operace dokončena, když aplikace obdrží SQL_SUCCESS nebo SQL_SUCCESS_WITH_INFO v původním volání funkce.

Do rozhraní ODBC 3.8, SQLCancelHandle byla přidána nová funkce. Tato funkce zruší šest funkcí připojení (SQLBrowseConnect, SQLConnect, SQLDisconnect, SQLDriverConnect, SQLEndTran a SQLSetConnectAttr). Aplikace by měla volat SQLGetFunctions, aby určila, zda ovladač podporuje SQLCancelHandle. Stejně jako u SQLCancel, pokud SQLCancelHandle vrátí úspěch, neznamená to, že operace byla zrušena. Aplikace by měla znovu volat původní funkci, aby určila, jestli byla operace zrušena. SQLCancelHandle umožňuje zrušit asynchronní operace u popisovačů připojení nebo popisovačů příkazů. Použití sqlCancelHandle ke zrušení operace v popisovači příkazu je stejné jako volání SQLCancel.

Není nutné současně podporovat jak operace SQLCancelHandle , tak asynchronní připojení. Ovladač může podporovat asynchronní operace připojení, ale ne SQLCancelHandle nebo naopak.

Asynchronní operace připojení a sqlCancelHandle mohou být také používány aplikacemi ODBC 3.x a ODBC 2.x s ovladačem ODBC 3.8 a správcem ovladačů ODBC 3.8. Informace o tom, jak povolit starší aplikaci používat nové funkce v novější verzi ODBC, naleznete v tématu Matice kompatibility.

Sdružování připojení

Při každém povolení sdružování připojení jsou asynchronní operace podporovány pouze pro vytvoření připojení (pomocí sqlConnect a SQLDriverConnect) a zavření připojení pomocí SQLDisconnect. Aplikace by ale měla být schopná zpracovat SQL_STILL_EXECUTING návratovou hodnotu z SQLConnect, SQLDriverConnect a SQLDisconnect.

Pokud je povolené sdružování připojení, podporují se pro asynchronní operace SQLEndTran a SQLSetConnectAttr .

Examples

A. Povolení asynchronního spouštění funkcí připojení

Následující příklad ukazuje, jak pomocí SQLSetConnectAttr povolit asynchronní spouštění pro funkce související s připojením.

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. Asynchronní operace potvrzení

Tento příklad ukazuje asynchronní operace potvrzování. Operace vrácení zpět je také možné provést tímto způsobem.

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;  
}  

Viz také

Spouštění příkazů ODBC