views:

180

answers:

3

I have a Win-CGI application I am currently converting to ISAPI.

The application uses the TDataset descendants for Extended Systems Advantage Database Server.

As there can be only one instance of a TAdsSettings object, this must be in the main thread.

TAdsQuery objects are needed in the request threads.

Will this work - that is, will the AdsQueries in the request threads pick up the global settings from the AdsSettings object in the main thread, and will this be thread safe?

A: 

Make sure the AdsQueries use Synchronize to access the TAdsSettings directly (or use a messaging system to comunicate between worker threads and main thread instead of accessing directly) if they are not in the main thread (i.e. System.MainThreadID <> Windows.GetCurrentThreadID)

François
Graza
+1  A: 

Yes, it will work. The TAdsSettings component modifies settings in the Advantage Client Engine (ACE), and with ISAPI there will be one instance of ACE loaded that all threads use.

I wouldn't recommend it, however. Depending on the settings you are changing it would make more sense to just call the ACE APIs directly. For example, if you are only setting the date format, it makes more sense to eliminate the TAdsSettings component and just call AdsSetDateFormat60, which takes a connection handle. Getting rid of the TAdsSettings component eliminates lots of calls to set ACE global settings. Many of those calls have to have a sync object to hold all connections off while the global is changed. That will have a negative performance impact, especially in a multi-threaded application like a web application. Instead make calls that operate on the specified connection handle.

You can get the connection handle by referencing the TAdsConnection.Handle property or calling the TAdsQuery.GetAceConnectionHandle method.

Jeremy Mullin
A: 

I also had asked this question in the newsgroup: devzone.advantagedatabase.com, Advantage.Delphi

For the sake of completeness, I'll add further question/answer from the rest of that thread:

Question (Me):

Many of the queries in threads are currently not attached to a TAdsConnection object. I'm planning to create a connection for each thread for these "orphan" queries to use, but it is a large application and this will take time. I'm also pretty sure that the only non-default property in the TAdsSettings object is the server-types set, which can also be set in the connection component, thus once all queries are linked to connections, the settings component wont be needed. I'll look into calling the settings API directly as an alternative.

In the meantime, I do have a question about threading and the queries with no connection component assigned. I noted from the help files that if queries in multiple threads share a single connection object, the queries will be run in series rather than concurrently. With a connection object in each thread, this should not be an issue, but I am wondering about the queries which do not have a connection object assigned. Will they be considered to be on independent connections from the point of view of multithreading concurrency, or will they be considered to be on the same connection and thus have to yield to each other?

Answer (Jeremy):

You will need to address this. They will just search a global list of connections to find one with the same path, and they will use that connection. Not good in a multi-threaded application.

Thus, from Jeremy's answer it is best to create at least one TAdsConnection object for each thread and ensure that all queries are attached to it, otherwise serialization may occur.

Graza