views:

84

answers:

1

I have to execute some code in the context of the main thread. I am using Lazarus + FPC. I receive an event from a thread inside a DLL (shared library if on linux) and my callback function gets called. Note that this function is not a member of any class but a standalone traditional function with a "cdecl" directive attached.

I have to triger a coresponding property event handler for each such message I receive. And these events have to be passed on in the context of the main thread. I know of two such solutions:

  1. PostMessage
  2. Application.QueueAsyncCall

The first one is ok, but it requires a window handle. And since this is a library code no handle is available. AllocateHWND is not an option since it is not cross platform. I know I can create a dummy form but this is a very bad solution

The second works ok, but I have a problem, that the call is not processed until I move a mouse inside application for instance. Maybe I am doing something wrong I don't know. I is just like my call is being processed only when message processing kicks in. But this can be a long wait apparently.

So I want to know what is the best solution here (probably QueueAsyncCall) and how I can be sure that my message (call) will be processed in acceptable timeframe?

+1  A: 

You can not be 100% sure, just like you can't in any non-realtime system. If the mainthread hangs, it won't check for messages or other events in the main loop. This is normal.

The only thing you can do is to avoid doing stuff in the mainthread that can take a long time. It's the trick of the trade to exactly judge what is necessary and what is not. Some realtime oriented people move all filesystem access to threads, and keep the GUI strictly for UI, just because if an user configures a path on a network share for this or the other, a problem with the share can easily cause a long timeout wait, of minutes even.

If I look at application.queueasynccall, I see no threadsafe processing (no locking or locked queues), so that one is out.

I know postmessage is emulated by Lazarus to some degree on non Windows, and I checked the implementation and it does have lock, so I assume it is multithreading safe.

Marco van de Voort
I am well aware that I cannot be 100% sure, but my app is doing nothing and still the calls are not processed until I move the mouse. So I am better of with PostMessage. But the drawback is that AllocateHWND is not yet implemented in crossplatform way. Or is it? I thought that Application.QueueAsyncCall was threadsafe. I will check the implementation. Thanks for the answer though. I have quite a lot of experience in multithreading enviroment but I am quite new to Lazarus. Thus the problems :)
Runner
The horror :) It is trully in no way threadsafe. So are there any alternative to messaging besides PostMessage. I mean simple one, no IPC or TCP/IP?
Runner
Not really. I assume they went through the trouble of implementing an postmessage emulation on other platforms for a reason.
Marco van de Voort
Runner: you wanted to send msgs to the mainthread, which has a form.handle or application.handle. The other way, to send messages to code outside of LCL control in a multiplatform way, or interprocess will be hard to impossible. The emulation is limited.
Marco van de Voort
I understand that. Maybe Application.Handle will suffice. In normal conditions it would be no problem, but this is a library, so there is no guarantie that a form will exist somewhere. I will look at Application.Handle. In the meantime I created a separated thread with internal event. Then I signal this event form the outside and the thread calls synchronize. This works under all platforms. The downside is, that synchronize blocks thread execution. But I worked that out too. Thanks for all the help. I will accept your answer.
Runner
See if tthread.queue exists (D2006+, don't know if already in FPC)
Marco van de Voort
No it doesn't. I looked for that as one of the first things. Neither does Applicaton.Handle. My solution with thread, event and synchronize now works cross platform and compiles without IFDEFs under FPC and Delphi. For now I will stick to that. Thanks for the suggestion.
Runner
I searched in bugrepo, and didn't find one. So I made a bugreport for it. It seems FPC's synchronize systems need to be redone for this, from a single slot to a queue, so don't hold your breath.
Marco van de Voort