View Issue Details

IDProjectCategoryView StatusLast Update
0013120LazarusLCLpublic2013-09-03 10:07
ReporterJonas Schäfer Assigned ToZeljan Rikalo  
PrioritynormalSeverityfeatureReproducibilityalways
Status closedResolutionfixed 
Product Version0.9.26 
Summary0013120: AsyncCalls (TApplication) are not handled until a message is received
DescriptionMe again.

I am using AsyncCalls from a thread and I have the problem that they are not handled until a normal message is received (MouseMove, Key or something). As I am using this as a replacement for the custom messages it is very annoying.

Sample attached.

greetings
Lord Horazont
Additional Informationi386-win32
TagsNo tags attached.
Fixed in Revision30403
LazTarget1.4
Widgetset
Attached Files

Relationships

related to 0018599 closedZeljan Rikalo Synchronize Events are not scheduled 

Activities

2009-02-05 17:41

 

asynccallqueue.zip (56,817 bytes)

Jonas Schäfer

2009-02-06 15:13

reporter   ~0025159

For those who are stucking with this, too: I recommend to send a WM_USER to any where you can handle it after you enqueued the async call and tell in the handler the application to re-check for async calls (Application.ProcessMessages)... I will do this until it is fixed/implemented.

greetings Lord Horazont

Henry Vermaak

2010-10-31 14:32

reporter   ~0042496

I'm pretty sure this is fixed for Windows, but maybe I'm wrong. I have this problem for gtk2, though. I have to wake up the main loop in the callback, otherwise I have to move the mouse before the call is executed. Just for reference, my code in my callback looks like this:

  Application.QueueAsyncCall(@Form1.NotifyAsync, 0);
  g_main_context_wakeup(g_main_context_default);

Henry Vermaak

2010-10-31 21:44

reporter   ~0042511

You can also wake up the main loop by using PostMessage with LM_PAINT, for example. You just have to build with -dusecthreads.

Is it a good idea to have code inside QueueAsyncCall to wake up the loop (non-blocking, of course)?

Henry Vermaak

2010-11-01 14:34

reporter   ~0042556

Just tested on Windows and behaviour is the same. I wasn't seeing this, because I registered device notification for a usb device, so those messages were waking up my app.

Zeljan Rikalo

2010-12-09 07:27

developer   ~0044113

qt widgetset shows same behaviour as gtk2.No QueueAsyncCalls() until input event comes (mouse, kbd).

Michael Schnell

2011-01-21 11:40

reporter   ~0045368

Last edited: 2011-01-21 11:47

The same issue is found with TThread.Synchronize on gtk.

For me this suggests to rework the code so that TThread.Synchronize and PostMessage (plus TThread.Queue and PostThreadMessage, when finally implemented) all call Application.QueueAsyncCall, so that the critical Event-Scheduler code is manageable in a single location.


I did a small example project (in fact an enhancement of the uasynccall.pas example I found somewhere). It should be working on all Widget Types (an on Delphi).

Same lets you select to test

 - TThread.Synchronize
 - TThread.Queue
 - PostMessage
 - PostThreadMessage
 - SendMessage
 - TForm.Dispatch
 - Application.QueuAsyncCall without parameters and
 - Application.QueuAsyncCall with parameters

From
 - A thread
 - A timer event and
 - A button event

If anybody might be inclined to put this project into the examples directory in the svn, I'd be happy to send the code.

Some testing results with Lazarus revision 29134 and fpGUI revision as of 20110120:

                     GTK2 / fpGUI
From a Thread ======= / =======
  Synchronize (*) / OK
  PostMessage OK / no function
  SendMessage (**) / no function
  Dispatch (**) / (***)
  QueueAsyncCall (*) / (****)

From a Timer
  Synchronize impossible
  PostMessage OK / no function
  SendMessage OK / no function
  Dispatch OK / OK
  QueueAsyncCall OK / (*****)


(*) The scheduled Events only are handled in the Main Thread when GUI Events for the Form are handled
(**) Forbidden but eventually works, The scheduled Events only are handled in the Main Thread when GUI Events for the Form are handled
(***) Forbidden; works for some time, then "SIGABRT"
(****) The scheduled Events only are handled in the Main Thread when the worker thread is terminated
(*****)Very funny: The scheduled Events only are handled in the Main Thread when e.g a completely unrelated worker thread is created and then terminated

Hope this helps,


-Michael (mschnell@lumino.de)

Michael Schnell

2011-01-24 10:26

reporter   ~0045444

Last edited: 2011-01-24 10:35

I did some tests with Revision 29185, Widget Type gtk2:

My test project prints a line on a memo in the procedure called by QueueAsyncCall.

If the memo that displays the messages resulting from the threads activity (via TThread.Synchronize or via Application.QueueAsyncCall) has the focus, the event does work. If the memo does not have the focus (as another control element on the Form or the Window of another application has the GUI focus) the queued Events do get handled in the main (GUI) thread.

Supposedly this queer behavior is the reason why the problem has not yet been detected by the testers.

Hope this helps,
-Michael

Henry Vermaak

2011-04-20 14:35

reporter   ~0047628

Zeljan, is there any reason not to call WakeMainThread at the end of QueueAsyncCall? This would probably fix this issue.

2011-04-20 14:40

 

queueasynccall_wakeup.patch (398 bytes)   
Index: lcl/include/application.inc
===================================================================
--- lcl/include/application.inc	(revision 30385)
+++ lcl/include/application.inc	(working copy)
@@ -2178,6 +2178,9 @@
     end;
     Last := lItem;
   end;
+
+  if Assigned(WakeMainThread) then
+    WakeMainThread(nil);
 end;
 
 procedure TApplication.RemoveAsyncCalls(const AnObject: TObject);
queueasynccall_wakeup.patch (398 bytes)   

Zeljan Rikalo

2011-04-20 14:43

developer   ~0047629

@Henry I don't know ... maybe you should ask Mattias or someone else who's more clever then me in this case.

Henry Vermaak

2011-04-20 14:57

reporter   ~0047631

Another thing I just noticed is that the QueueAsyncCall is not thread safe. This may bite people. Why is QueueAsyncCall implemented with a linked list instead of e.g. a thread safe queue based on TQueue? Can Mattias comment?

Zeljan Rikalo

2011-04-20 15:44

developer   ~0047632

Test and close if ok. I've tested gtk,gtk2,qt and win32 under wine and looks good.

Issue History

Date Modified Username Field Change
2009-02-05 17:41 Jonas Schäfer New Issue
2009-02-05 17:41 Jonas Schäfer File Added: asynccallqueue.zip
2009-02-05 18:07 Vincent Snijders LazTarget => post 1.2
2009-02-05 18:07 Vincent Snijders Severity major => feature
2009-02-05 18:07 Vincent Snijders Status new => acknowledged
2009-02-06 15:13 Jonas Schäfer Note Added: 0025159
2010-10-31 14:32 Henry Vermaak Note Added: 0042496
2010-10-31 21:44 Henry Vermaak Note Added: 0042511
2010-11-01 14:34 Henry Vermaak Note Added: 0042556
2010-12-09 07:27 Zeljan Rikalo Note Added: 0044113
2011-01-21 11:40 Michael Schnell Note Added: 0045368
2011-01-21 11:44 Michael Schnell Note Edited: 0045368
2011-01-21 11:45 Michael Schnell Note Edited: 0045368
2011-01-21 11:47 Michael Schnell Note Edited: 0045368
2011-01-24 10:26 Michael Schnell Note Added: 0045444
2011-01-24 10:27 Michael Schnell Note Edited: 0045444
2011-01-24 10:34 Michael Schnell Note Edited: 0045444
2011-01-24 10:35 Michael Schnell Note Edited: 0045444
2011-01-24 11:52 Zeljan Rikalo Relationship added related to 0018599
2011-04-20 14:35 Henry Vermaak Note Added: 0047628
2011-04-20 14:40 Henry Vermaak File Added: queueasynccall_wakeup.patch
2011-04-20 14:43 Zeljan Rikalo Note Added: 0047629
2011-04-20 14:57 Henry Vermaak Note Added: 0047631
2011-04-20 15:44 Zeljan Rikalo Fixed in Revision => 30403
2011-04-20 15:44 Zeljan Rikalo Status acknowledged => resolved
2011-04-20 15:44 Zeljan Rikalo Resolution open => fixed
2011-04-20 15:44 Zeljan Rikalo Assigned To => Zeljan Rikalo
2011-04-20 15:44 Zeljan Rikalo Note Added: 0047632
2011-12-01 10:26 Marc Weustink Status resolved => closed
2013-09-03 10:07 Martin Friebe LazTarget post 1.2 => 1.4