Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2010-01

Application.QueueAsyncCall()

12 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Brad Campbell

Is QueueAsyncCall() threadsafe?

Let's say I have a communications child thread and I want to trigger a call back in the main GUI thread. Traditionally I'd do something ugly like have a timer polling a variable used as a flag, or polling a RtlEvent on a short timeout, but this seems like a much nicer solution.

Also, is there any form of mutex or lock I can use to protect access to a linked list shared between threads? It would appear that RTLCriticalSection might do what I want.

Regards,
Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

cobines
to Brad Campbell

2010/1/20 Brad Campbell :

Is QueueAsyncCall() threadsafe?

As far as I know it is not.

Show quoted text 6 lines
Let's say I have a communications child thread and I want to trigger a call back in the main GUI thread. Traditionally I'd do something ugly like have a timer polling a variable used as a flag, or polling a RtlEvent on a short timeout, but this seems like a much nicer solution.

You can call TThread.Synchronize(), your thread will be stopped until the GUI thread executes your function.

Other solution is to create a separate thread for handling such GUI functions (take a look at attached source); this doesn't stop your child thread. Be careful however because in this case you don't control when your method is called (it may be after your thread is already finished).

Also, is there any form of mutex or lock I can use to protect access to a linked list shared between threads? It would appear that RTLCriticalSection might do what I want.

Yes, it will do fine. The TCriticalSection is just a wrapper over RTLCriticalSection.

cobines -------------- next part -------------- A non-text attachment was scrubbed... Name: uGuiMessageQueue.pas Type: text/x-pascal Size: 5138 bytes Desc: not available URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20100120/74721502/attachment.bin>

Reply by email

Brad Campbell
to cobines
cobines wrote 13 lines
2010/1/20 Brad Campbell : > Is QueueAsyncCall() threadsafe? As far as I know it is not. > Let's say I have a communications child thread and I want to trigger a call > back in the main GUI thread. Traditionally I'd do something ugly like have a > timer polling a variable used as a flag, or polling a RtlEvent on a short > timeout, but this seems like a much nicer solution. > You can call TThread.Synchronize(), your thread will be stopped until the GUI thread executes your function.

Yeah, but what I'm trying to do is have the main gui thread sit on its hands until it has a message waiting for it. Then I'd like to have it wakeup on an event rather than spinning or polling, while still remaining responsive to user input.

Show quoted text 5 lines
Other solution is to create a separate thread for handling such GUI functions (take a look at attached source); this doesn't stop your child thread. Be careful however because in this case you don't control when your method is called (it may be after your thread is already finished).

That's a really interesting solution. I *thought* the issue was that the update of GUI elements must only be done in the main thread. I actually don't have a problem running the callbacks from the comms thread as the callbacks are executed between packets in a polled system, so it's not at all timing critical. I was more concerned with updating the GUI components in a threadsafe manner.

Unless I'm mistaken (and I'm pretty green at thread stuff still) it looks like you are running a separate thread that checks a message queue and runs the callbacks from there, so you are possibly updating gui components from a thread other than the main thread. Is that kosher?

Really appreciate the reply, it has been incredibly helpful.

Regards,
Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

cobines
to Brad Campbell: Yeah, but what I'm trying to do is have the main gui thread sit on its hands until it has…

2010/1/21 Brad Campbell :

Yeah, but what I'm trying to do is have the main gui thread sit on its hands until it has a message waiting for it. Then I'd like to have it wakeup on an event rather than spinning or polling, while still remaining responsive to user input.

Polling is the only way to check for messages. If you block the main thread waiting for an event your application will be unresponsive; it needs to be in a constant loop. The async queue is checked every iteration so eventually your callback will be called.

Unless I'm mistaken (and I'm pretty green at thread stuff still) it looks like you are running a separate thread that checks a message queue and runs the callbacks from there, so you are possibly updating gui components from a thread other than the main thread. Is that kosher?

No, the callbacks are run from CallMethods() which is called via Synchronize(), so they are run from the main thread. But instead of the thread that queued the callback being blocked it is the thread from GuiMessageQueue that is blocked. That way a worker thread can run uninterrupted.

If you're not worried about your worker thread pausing from time to time to update the GUI, then using Synchronize is prefferable.

cobines

Reply by email

waldo kitty
to cobines
cobines wrote
If you're not worried about your worker thread pausing from time to time to update the GUI, then using Synchronize is prefferable.

as in how much "time"?? is this a standard setting or something related to all other processing??

Reply by email

cobines
to waldo kitty

2010/1/21 waldo kitty :

Show quoted text 7 lines
On 1/20/2010 21:01, cobines wrote: > > If you're not worried about your worker thread pausing from time to > time to update the GUI, then using Synchronize is prefferable. as in how much "time"?? is this a standard setting or something related to all other processing??

It is undefined. The worker thread must wait until GUI thread finishes processing current message(s) and checks the call queue.

cobines

Reply by email

Brad Campbell
to Flávio Etrusco: In Delphi the queued method is run on the (context of) the main/GUI thread. -Fl?vio
Fl?vio Etrusco wrote 5 lines
On Wed, Jan 20, 2010 at 5:54 AM, Brad Campbell wrote: > Is QueueAsyncCall() threadsafe? > In Delphi the queued method is run on the (context of) the main/GUI thread.

Which is precisely what I want. The issue is not the context of the queued method, but the method used to poke the event onto the application event queue being threadsafe.

I'm almost thinking of using a unix socket and using the socket in AddEventHandler() to watch for a signal in the main loop.

Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

Flávio Etrusco
to Brad Campbell
Brad Campbell wrote 18 lines
Fl?vio Etrusco wrote: > > On Wed, Jan 20, 2010 at 5:54 AM, Brad Campbell wrote: >> >> Is QueueAsyncCall() threadsafe? >> > > In Delphi the queued method is run on the (context of) the main/GUI > thread. Which is precisely what I want. The issue is not the context of the queued method, but the method used to poke the event onto the application event queue being threadsafe. I'm almost thinking of using a unix socket and using the socket in AddEventHandler() to watch for a signal in the main loop. Brad

Yes, the procedure itself is (meant to be) threadsafe.

-Fl?vio

Reply by email

Flávio Etrusco
to Flávio Etrusco

2010/1/21 Fl?vio Etrusco :

Show quoted text 24 lines
On Thu, Jan 21, 2010 at 9:17 AM, Brad Campbell wrote: > Fl?vio Etrusco wrote: >> >> On Wed, Jan 20, 2010 at 5:54 AM, Brad Campbell wrote: >>> >>> Is QueueAsyncCall() threadsafe? >>> >> >> In Delphi the queued method is run on the (context of) the main/GUI >> thread. > > Which is precisely what I want. The issue is not the context of the queued > method, but the method used to poke the event onto the application event > queue being threadsafe. > > I'm almost thinking of using a unix socket and using the socket in > AddEventHandler() to watch for a signal in the main loop. > > Brad Yes, the procedure itself is (meant to be) threadsafe. -Fl?vio

Oops, sorry! Scrap what I said :-$ I was thinking about Delphi TThread.QueueAsync<something>... Lazarus' Application.TAsyncCallQueues isn't threadsafe AFAICS from the code.

-Fl?vio

Reply by email

Brad Campbell
to Flávio Etrusco
Fl?vio Etrusco wrote
Oops, sorry! Scrap what I said :-$ I was thinking about Delphi TThread.QueueAsync<something>... Lazarus' Application.TAsyncCallQueues isn't threadsafe AFAICS from the code.

No, it would appear not. Nevermind, it turns out it's only called at the start of the idle handler in any case, so if the application is idle, it's no better than me polling with a timer.

Surely there is a cross-platform, threadsafe way for me to alert the main thread there is something I want it to respond to *now*.

Oh well, I'll keep looking.

Regards,
Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email

Brad Campbell
to Brad Campbell: Is QueueAsyncCall() threadsafe? Let's say I have a communications child thread and I want…
Brad Campbell wrote 6 lines
Is QueueAsyncCall() threadsafe? Let's say I have a communications child thread and I want to trigger a call back in the main GUI thread. Traditionally I'd do something ugly like have a timer polling a variable used as a flag, or polling a RtlEvent on a short timeout, but this seems like a much nicer solution.

After reading the source for TThread.Synchronize() I see it already implements the round thing with spokes and a hub that I've been so busily trying to re-implement. A total lack of understanding on my part. Thanks for everyones help.

Regards,
Brad

Dolphins are so intelligent that within a few weeks they can train Americans to stand at the edge of the pool and throw them fish.

Reply by email