-1

Using Delphi 7 & UIB, I'm running database operations in a background thread to eliminate problems like:

  • Timeout
  • Priority
  • Immediate Force-reconnect after network-loss
  • Non-blocked UI
  • Keeping an opened DB connection alive
  • User canceling

I've read ALL related topics here, and realized: using while isMyThreadStillRuning and not UserCanceled do sleep(100); end; isn't the recommended way to do this, but rather using TEvent.WaitFor(3000)....
The solutions here are either about sending signals FROM or TO... the thread, or doing it with messages, but never both ways.

Reading the help file, I've also found TSimpleEvent, which seems to be easier to use.

So what is the recommended way to communicate between Main-UI + DB-Thread in both ways?

Should I simply create 2+2 TSimpleEvent?

  • to start a new transaction (thread should stop sleeping)
  • force-STOP execution
  • to signal back if it's moved to a new stage (transaction started / executed / commited=done)
  • to signal back if there is any error happened

or should there be only 1 TEvent?

Update 2:
First tests show:

  • 2x TSimpleEvent is enough (1 for Thread + 1 for Gui)
  • Both created as public properties of the background thread
  • Force-terminating the thread does not work. (Too many errors impossible to handle..)
  • Better to set a variable like (Stop_yourself) and let it cancel and free itself, (while creating a new instance from the same class and try again.)
  • (still work in progress...)
SzakiLaci
  • 347
  • 1
  • 16
  • This "event-driven-thread-communication" method is new to me, and I do not know enough to decide how many of these events should I use and what kind of them? Is it faster to reduce the number and use thread-safe signals, or the CPU consumption is so minimal that it's not worth the hassle compared to multiple TSimpleEvents? – SzakiLaci Sep 19 '19 at 17:57
  • I think you might be getting a bit too carried away with "events" and would probably do better to have a very simple thread whose `Execute` runs a message loop which waits for custom messages sent from the GUI thread using `PostThreadMessage` - results can be sent back to the GUI thread using `Synchonise`. Everything you've mentioned can be done with that kind of arrangement. But I think you'll find getting that right will be quite difficult enough to begin with, so best to keep it simple. – MartynA Sep 19 '19 at 18:22
  • Looks like you are recreating asynchronous queries which some data access components already support. – Brian Sep 20 '19 at 11:50
  • @MartynA `Synchronise` is a blocking mechanism. Events are not. The final goal is to inform the user about database connection & execution stages **without** blocking it. – SzakiLaci Sep 21 '19 at 09:29
  • @Brian Actually yes! Since there are no working version of free components supporting Firebird + D7 I know about. Or can you name any? An other advantage is to write it myself to have full control with minimal overhead. Sadly -after 3 days- I had to realize it's not so simple and I'm still a few days away from tests. I have Questions like: **1.)** When should I reset an event & from which thread? **2.)** When can `wrAbandoned` or `wrError` happen and how to deal with them? **3.)** should I create Events inside or outside the Thread? ... _Life is never simple. You have to deal with everything._ – SzakiLaci Sep 21 '19 at 09:38
  • Having to deal with everything is a good reason for keeping things simple and I still think that using events may be unnecessarily complicating things. If you don't like Synchronize then post messages back to the GUI from your thread to communicate back to it. – MartynA Sep 21 '19 at 10:25
  • @MartynA And how should I wait during thread inactivity, or while waiting at the gui? Can you write a short code how it would work without things like this: `case Event.WaitFor(200) of wsTimeOut: ...;` ? – SzakiLaci Sep 22 '19 at 10:48
  • 1
    See e.g. [the accepted answer to this q](https://stackoverflow.com/questions/13931782/messageloop-within-thread) and, of course, the thread can post messages back to the application. – MartynA Sep 22 '19 at 10:57
  • I've found a very good answer [here ...](https://stackoverflow.com/a/15575701/2110862) Will try to implement it in a few years and share the final code if it's working stable. – SzakiLaci May 24 '23 at 06:59

1 Answers1

0

You should move the query to a TThread. Unfortunately, anonymous threads are not available in D7 so you need to write your own TThread derived class. Inside, you need its own DB connection to prevent shared resources. From the caller method, you can wait for the thread to end. The results should be stored somewhere in the caller class. Ensure that the access to parameters of the query and for storing the result of the query is handled thread-safe by using a TMutex or TMonitor.

  • 1
    Of course! But not **just** the query, the `TUIBDatabase + TUIBTransaction` too. That is not the question here, only how to communicate between the 2 threads. Anyway it is a good thing you share for newbies reading this post. Also important to mention: the shared variables should be thread-safe! _(You may add that to your post too by editing it.)_ – SzakiLaci Sep 19 '19 at 18:03