Asynchronous Mode
Normally, calls made by a client application to a database server are blocking. This means that the client application has to wait for server replies each time it submits an SQL statement or when it attempts to fetch rows. The effect of this is that the end user may feel that the application is not sufficiently responsive.
Asynchronous mode, which is supported by some database systems, can be used to increase application responsiveness. Instead of blocking until the server responds, asynchronous calls return quickly and the caller must check whether the call has completed (that is, whether the server has responded). If not, the caller is expected to repeat the call until completion. In the meantime, the caller can proceed with other tasks (such as giving the main loop a chance to handle other events).
The advantages of asynchronous mode are that the application can become more responsive to user input and, in addition, the user may be given the opportunity to cancel a long-running task that has taken too much time. The disadvantage is that programming applications with asynchronous calls is more difficult than programming with synchronous calls.
The IliSQLTable class supports selecting and fetching rows asynchronously from a database server. It does not, however, support asynchronous insert, update, or delete operations.
A typical way of using asynchronous calls is to set up a timer in the application (see the IliDbTimer class) and to proceed as follows. Assume that an SQL data source needs to perform its select call in asynchronous mode.
-
Put the data source session in asynchronous mode:
IliSQLDataSource* ds = ...; IliSQLTable* sqlTable = ds->getSQLTable(); IliSQLSession session = ds->getEffectiveSQLSession(); session->enterAsyncMode(); |
-
Ensure that the fetch policy is “Immediate” so that a call to the select member function will also fetch all rows:
sqlTable->setFetchPolicy(IliFP_Immediate);
-
Call the select member function:
sqlTable->select();
-
In the timer callback, call continueAsyncCall as long as the call to select has not completed:
void ILVCALLBACK OnTimer(IlvGraphic*, IlAny) { IliSQLDataSource* ds = ...; IliSQLTable* sqlTable = ds->getSQLTable(); if (!sqlTable->isAsyncCallCompleted()) sqlTable->continueAsyncCall(); } |
Note that asynchronous mode is not supported by all database systems. Moreover, when it is supported by a database system, support may depend on the database server release number. You should dynamically test whether asynchronous mode is supported as shown in the following code:
IliSQLSession* session = sqlTable->getEffectiveSQLSession();
if (session->supportsAsyncMode()) {
...
}
Another important issue to consider is that there can be at most one non-completed asynchronous call among all cursors that belong to the same session. This means that you cannot execute asynchronously in parallel two SQL statements through two cursors that belong to the same session. Consequently, it is recommended that an SQL table have a private SQL session (that is, not an application-defined session) when used in asynchronous mode.