djsoft
djsoft

Reputation: 1071

FireDAC amBlocking vs amNonBlocking command execution

I use FireDAC mostly from background threads with occasional use from the main GUI thread.

According to the docs, there are 4 possible execution modes, from which only 2 seem to be appropriate in my case:

amBlocking The calling thread and GUI are blocked until an action is finished.

This one is the default and seem to be working fine. Although I'm not happy that it says "and GUI are blocked" - I don't need to block the GUI while background thread does the job. This sort of defeats the purpose of the threads. It can also lead to non-obvious deadlocks.

amNonBlocking The calling thread is blocked until an action is finished. The GUI is not blocked.

This mode seems more appropriate, as it blocks only the calling thread, and this appears to be what I need. But in practice, it's not. From time to time the call fails with exception

EFDException [FireDAC][Phys][SQLite]-326. Cannot perform the action, because the previous action is in progress.

All calls to FireDAC across all threads are serialized with a critical section - according to docs this is enough for thread safe operation of FireDAC. All datasets/queries are closed before critical section is released.

The main question is, what execution mode to choose? Sub-question is - is it a bug in FireDAC and amNonBlocking is broken?

Upvotes: 2

Views: 1780

Answers (1)

djsoft
djsoft

Reputation: 1071

In case anyone has the same problem, the solution is as follows, before any operation with a database, call:

  if GetCurrentThreadId = MainThreadID then
    FDConn.ResourceOptions.CmdExecMode := amBlocking
  else
    FDConn.ResourceOptions.CmdExecMode := amNonBlocking;

Upvotes: 2

Related Questions