--- description: "Asynchronous Execution (Notification Method)" title: "Asynchronous Execution (Notification Method) | Microsoft Docs" ms.custom: "" ms.date: "01/19/2017" ms.prod: sql ms.prod_service: connectivity ms.reviewer: "" ms.technology: connectivity ms.topic: conceptual ms.assetid: e509dad9-5263-4a10-9a4e-03b84b66b6b3 author: David-Engel ms.author: v-daenge --- # Asynchronous Execution (Notification Method) ODBC allows asynchronous execution of connection and statement operations. An application thread can call an ODBC function in asynchronous mode and the function can return before the operation is complete, allowing the application thread to perform other tasks. In the Windows 7 SDK, for asynchronous statement or connection operations, an application determined that the asynchronous operation was complete using the polling method. For more information, see [Asynchronous Execution (Polling Method)](../../../odbc/reference/develop-app/asynchronous-execution-polling-method.md). Beginning in the Windows 8 SDK, you can determine that an asynchronous operation is complete using the notification method. In the polling method, applications need to call the asynchronous function each time it wants the status of the operation. The notification method is similar to callback and wait in ADO.NET. ODBC, however, uses Win32 events as the notification object. The ODBC Cursor Library and ODBC asynchronous notification cannot be used at the same time. Setting both attributes will return an error with SQLSTATE S1119 (Cursor Library and Asynchronous Notification cannot be enabled at the same time). See [Notification of Asynchronous Function Completion](../../../odbc/reference/develop-driver/notification-of-asynchronous-function-completion.md) for information for driver developers. > [!NOTE] > The notification method is not supported with cursor library. An application will receive error message if it attempts to enable cursor library via SQLSetConnectAttr, when the notification method is enabled. ## Overview When an ODBC function is called in asynchronous mode, the control is returned to the calling application immediately with the return code SQL_STILL_EXECUTING. The application must repeatedly poll the function until it returns something other than SQL_STILL_EXECUTING. The polling loop increases CPU utilization, causing poor performance in many asynchronous scenarios. Whenever the notification model is used, the polling model is disabled. Applications should not call the original function again. Call [SQLCompleteAsync Function](../../../odbc/reference/syntax/sqlcompleteasync-function.md) to complete the asynchronous operation. If an application calls the original function again before the asynchronous operation is complete, the call will return SQL_ERROR with SQLSTATE IM017 (Polling is disabled in Asynchronous Notification Mode). When using the notification model, the application can call **SQLCancel** or **SQLCancelHandle** to cancel a statement or connection operation. If the cancel request is successful, ODBC will return SQL_SUCCESS. This message does not indicate that the function was actually canceled; it indicates that the cancel request was processed. Whether the function is actually canceled is driver-dependent and data source-dependent. When an operation is canceled, the Driver Manager will still signal the event. The Driver Manager returns SQL_ERROR in the return code buffer and the state is SQLSTATE HY008 (Operation canceled) to indicate the cancelation is successful. If the function completed its normal processing, the Driver Manager returns SQL_SUCCESS or SQL_SUCCESS_WITH_INFO. ### Downlevel Behavior The ODBC Driver Manager version supporting this notification on complete is ODBC 3.81. |Application ODBC Version|Driver Manager Version|Driver Version|Behavior| |------------------------------|----------------------------|--------------------|--------------| |New application of any ODBC version|ODBC 3.81|ODBC 3.80 Driver|Application can use this feature if the driver supports this feature, otherwise the Driver Manager will error out.| |New application of any ODBC version|ODBC 3.81|Pre-ODBC 3.80 Driver|The Driver Manager will error out if the driver does not support this feature.| |New application of any ODBC version|Pre-ODBC 3.81|Any|When the application uses this feature, an old Driver Manager will regard the new attributes as driver-specific attributes, and the driver should error out. A new Driver Manager will not pass these attributes to the driver.| An application should check the Driver Manager version before using this feature. Otherwise, if a poorly written driver does not error out and the Driver Manager version is pre ODBC 3.81, behavior is undefined. ## Use Cases This section shows use cases for asynchronous execution and the polling mechanism. ### Integrate Data from Multiple ODBC Sources A data integration application asynchronously fetches data from multiple data sources. Some of the data are from remote data sources and some data are from local files. The application cannot continue until the asynchronous operations are completed. Instead of repeatedly polling an operation to determine if it is complete, the application can create an event object and associate it with an ODBC connection handle or an ODBC statement handle. The application then calls operating system synchronization APIs to wait on one event object or many event objects (both ODBC events and other Windows events). ODBC will signal the event object when the corresponding ODBC asynchronous operation is completed. On Windows, Win32 event objects will be used and that will provide the user a unified programming model. Driver Managers on other platforms can use the event object implementation specific to those platforms. The following code sample demonstrates the use of connection and statement asynchronous notification: ``` // This function opens NUMBER_OPERATIONS connections and executes one query on statement of each connection. // Asynchronous Notification is used #define NUMBER_OPERATIONS 5 int AsyncNotificationSample(void) { RETCODE rc; SQLHENV hEnv = NULL; SQLHDBC arhDbc[NUMBER_OPERATIONS] = {NULL}; SQLHSTMT arhStmt[NUMBER_OPERATIONS] = {NULL}; HANDLE arhDBCEvent[NUMBER_OPERATIONS] = {NULL}; RETCODE arrcDBC[NUMBER_OPERATIONS] = {0}; HANDLE arhSTMTEvent[NUMBER_OPERATIONS] = {NULL}; RETCODE arrcSTMT[NUMBER_OPERATIONS] = {0}; rc = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &hEnv); if ( !SQL_SUCCEEDED(rc) ) goto Cleanup; rc = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3_80, SQL_IS_INTEGER); if ( !SQL_SUCCEEDED(rc) ) goto Cleanup; // Connection operations begin here // Alloc NUMBER_OPERATIONS connection handles for (int i=0; i