After several hours of testing, I came to the reluctant conclusion that nothing works in the program when this type of thread is executing - somewhat negating the whole point of having a thread! I've restored the program to how it was on Saturday night: the interface form calculates the correlations and saves the data in an instance of the temp table. A secondary form is called to display the data.
I've been experimenting on a separate copy of the program units, and it appears that something connected with the database code in the thread is causing the problem. I'm using completely different database components and not accessing any units whatsoever but there the problem still exists.
So, I wondered, what else can I do? An old solution popped into my head: execute a separate program to do the work. This program can be passed whatever parameters are necessary, and can send a message to the main program that data is waiting to be displayed. But it's not always necessary to execute a separate program: if there aren't that many data points to be calculated then it's quicker to do this within the existing program. I determined that - on my computer - 2500 records is approximately the tipping point.
The first part of the code - entering into the temp table the records that will act as the input for the correlation code - remains in the interface unit. Instead of having to issue a separate query in order to determine how many tuples have been inserted, I simply store the return value of the ExecSQL function. Almost always I ignore the return value, which is the number of tuples affected by the query. In this case, the number of tuples will be the number of tuples inserted which is the total number of examinees.
If this number is less than 2500 then the original code executes within the interface unit; at the end, the son form is created directly to display the data. Should there be more than 2500 tuples, then first a string is built with all the parameters that need to be passed, eg '21 15 12 01/01/22'. Then the external program is executed, receiving this string. It turns out that almost all of the thread code that I wrote could be transferred without change into the external program, including all the database code. In order to simplify matters for myself, I am using the InterBase components as opposed to the dbExpress components that I normally use. Again, this program does not include any module from the main program.
The final line in this program is 'sendmessage (hwnd_broadcast, RegisterWindowMessage ('Show correl'), rinstance, 0)'; this sends a message to every open program on the computer (because the program doesn't know who executed it) with a message number that is not necessarily constant; also using the RegisterWindowMessage technique means that the message number is known only to this pair of programs. I discussed1 this Windows technique way way back in 2009. The call arrives at the overridden DefaultMessage handler that calls the secondary form to display the data.
Finally, success.
Internal links
[1] 176
Title | Tags | ||
---|---|---|---|
1348 | PrioXRef 3 - insert without parameters | Programming | |
1538 | Indexing blogs | Programming, Meta-blogging, Blog manager program | |
1678 | The running grave | Cormoran Strike |
No comments:
Post a Comment