This may be hard to debug....
Where you able to get a stacktrace, with symbols?
I am not sure I have time to go through your sources....
But to start, here is what I would do in debugging>
Either
1) (slow)
set a breakpoint (properties, do NOT break but take a snapshot) in begin/end update. (and other places, if any, that get the lock)
Then when it happen, open debug history, and check for who got the paintlock.
(leave the stack window open, while taking snapsots, and you will get more than 5 lines of stack per snap)
2) the same, but use debugln
if you add debugln at the caller level, then you need no trace.
Also, assuming that you eventually call EndUpdate you should get
debugln('Returning from Paintlock, wich had Paint called while active');
DumpStack;
But those checks are not complete, if there are furthe BeginPaintlock before that, then they may not happen. You need to add guards to all other write access to FInvalidateRect.
(for that -using ifdef- you can send the patch / may be helpful for others too).
----------------------
You can also add flags when your threads are working, and catch calls to BeginUpdate....
(or use breakpoints, that will enable/disable other breakpoint... but that is slower and more work)