Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find out why application thread messages go missing with TSaveDialog

Developing with RAD Studio (Delphi) v10.2.1 (Tokyo release 1) on Windows 10 "Creators Update" 64bit, but 32bit development.

The application is VCL with multiple background threads, each using Indy TidHTTP to fetch network resources. Synchronisation between the main thread and the background threads is implemented using message queues (PostThreadMessage calls). This is complicated enough that offering direct code here would be difficult and messy, so I'm starting with a verbal description.

What is supposed to happen: Open a file with links to external resources, this generates the HTTP requests and hands them out to background processing, then waits for incoming messages on the application message queue to say the resources have been downloaded. The application messages are matched in event code assigned to TApplication.OnMessage (which, I suspect, is where my problem lies).

It works. Everything goes smoothly most of the time. But if I open a TSaveDialog - even if I cancel the dialog rather than actually doing anything - then messages go missing off the application message queue.

Through a process of writing log messages (it's impossible to debug directly because that upsets the timing required to cause the problem) I've worked out that the background threads are indeed posting the messages (and getting a positive response from PostThreadMessage), but they never appear on my TApplication.OnMessage event code.

I've seen that some sneaky code in various libraries will set up their own PeekMessage/TranslateMessage/DispatchMessage loops, but not all of them remember to check if there is a TApplication.OnMessage event. But I've just searched through the VCL code and the dozen or so third party libraries I'm using and have not found any instances of this that would be getting hit in this case (as far as I can tell).

Note: I am using madExcept, Indy, FastReport, AddictSpell, SynEdit, VclStyleUtils (amongst a few other less known libraries)

Note 2: I am wondering if it might be related to with Delphi 10.2.1 or Windows 10 Creator's update, since I am also seeing some other odd behaviour (long delays with the first exception or first TOpenDialog - but only on some applications) that definitely didn't happen with 10.1 (I didn't use 10.2.0). ... But this may be (probably is) something different.

So my question is: What can I do about this?

Any suggestions on how to find/verify that there is some other code stealing the application messages? Anything else I should search for other than PeekMessage?

Is there another way to intercept the application message queue messages that might let me avoid the problem?

If no better options show themselves I may have to abandon using application thread messages and implement my own messaging/synchronisation system, which I'd rather not do after getting this other working very well the rest of the time.

like image 477
GeoffW Avatar asked Aug 31 '17 14:08

GeoffW


1 Answers

You mention PostThreadMessage. Look no further. You can't use this unless you control all message loops that might pull off thread messages, and you don't. The modal file dialog message loop is out of your control. It will pull off thread messages intended for a different message loop, and not know what to do with them.

The solution is simple enough. Post messages to a window rather than a thread. That way all sane message loops (the modal file dialog's message loop is sane) will dispatch the messages to the intended recipient window.

In Delphi terms this would involve using AllocateHWnd or similar to create a hidden window to receive the messages.

Raymond Chen has covered this topic here: Why do messages posted by PostThreadMessage disappear?

like image 195
David Heffernan Avatar answered Oct 30 '22 13:10

David Heffernan