Recent

Author Topic: [SOLVED]error when modifying main form from indy thread  (Read 14511 times)

rvk

  • Hero Member
  • *****
  • Posts: 3842
Re: [SOLVED]error when modifying main form from indy thread
« Reply #45 on: October 28, 2015, 02:00:58 pm »
O wow, for Windows you can indeed remove the ProcessMessages in my simple_postmessage.zip. BUT... on Linux you DO need the ProcessMessages. Otherwise the lines in memo1 don't get displayed until ALL messages are handled !!!
erm that explanation doesn't make sense to me.
It wasn't an explanation. It was an observation. It also puzzles me why this is happening.
This is what's going on... (with my simple-example and no threads)
When running the loop with 20.000 postmessages
Code: Pascal  [Select]
  1.   for p := 1 to 20000 do
  2.   begin
  3.     PostMessage(Self.Handle, LM_POST_MESSAGE, p, p);
  4.     Button1.Caption := IntToStr(p);
  5.   end;
In Windows you see the button-caption running up. In Linux it directly displays 20.000. So the Windows-messaging somehow seems to keep doing the Paint for your form (even in a tight loop, maybe because of the PostMessage). In Linux paint-handling is only performed AFTER this procedure.

Now for the post_message() procedure:
Code: Pascal  [Select]
  1. procedure TForm1.post_message(var Msg: TLMessage);
  2. begin
  3.   Memo1.Lines.add('p = ' + IntToStr(Msg.wParam) + ' ' + IntToHex(Integer(sPtr),4));
  4.   //Application.ProcessMessages;
  5. end;
In Windows the same happens. Without the ProcessMessages it can still paint the Memo1. So in Windows you see all the lines appear after each other. In Linux nothing seems to happen and the memo1 is only updated when ALL the post_messages are processed. Only if you use the ProcessMessages you'll see them appear sequentially.

So somehow under Windows there is a separate process which handles the messaging for handing the painting and it runs besides the "normal" PostMessages-handling. Under Linux all messages (paint and post etc) are handled sequentially so the painting of the form is only performed at the end when all post_messages are processed (or when you insert a ProcessMessages).

I hope I explained this clearly. But it demonstrates that the messaging-handling under Linux is way less advanced (or flexible) (?).

Quote
Is it linux or gtk? If compiled as a QT application does it have the same problem? I'm asking because I think that QT hsa its own message queue implementation that is similar with the windows message queue.
I used gtk (Debian, Lazarus 1.5 r48991M FPC 2.6.5 i386-linux-gtk 2)

Quote
Oh wait I have a 32bit linux now I can test my self!! Let me do that and get back to you.
You'll see for yourself what I meant by above "observation" :)


Note: B.T.W. All this is (probably) unrelated to the problem we're having when using PostMessage in a thread under Linux. I understand that SendMessage is a problem (because it is still executed in the thread which calls is, I checked this) but PostMessage should be handled differently and in the correct thread (I also checked this). But there is still a problem when using PostMessage in threads (when you use about 1000 to 1500 it crashes).

taazz

  • Hero Member
  • *****
  • Posts: 5363
Re: [SOLVED]error when modifying main form from indy thread
« Reply #46 on: October 31, 2015, 06:28:57 am »
It wasn't an explanation. It was an observation. It also puzzles me why this is happening.
OK. here is what I see on my memo when I run the application in opensuse 13 32bit.
Code: [Select]
3067414656:2956725056 :: 2956725056.SendMessage :596
3067414656 | Terminating... @165564669
3067414656 | Waiting... @165564669
3067414656 | [No Result] @165564681
3067414656 | Freeing... @165564686
Click "Create Server Thread" to start..
what you see on the first line, from left to right, <ApplicationThreadID>:My_Server_Thread.ThreadID :: <GetCurrentThreadID>.SendMessage etc etc etc. This is proof that the message handling procedure is invoked from the thread that send the message instead of the application main thread. Any access to lcl components inside that handler is unsafe and should be avoided at all costs. In fact I think its some strange luck that allowed us to see anything in the memo so far or simple the QT library has better multi threading support. I'm going to run the same test on GTK and see the differences there. After I'm done testing I'll attach some screenshots too and if I manage it a gif showing the application updating it self with the update level set to none. By the way I made a couple of changes on the application namely I removed all access to lcl controls from the thread class and ofcourse removed all the calls to ProcessMessages in the main form too, except the one in the Do_updates procedure.

Overall it seems that SendMessage does not do what advertises under QT and I'm afraid under GTK too.

Edit:
Just in case I get side tracked again here is the test with all the changes I made. Make sure that you choose none for update method before pressing the create server button.Added a screenshot from a windows test too to show the difference in execution.

Code: [Select]
3067414656: :: 3067414656.PostMessage :36283 @173038895
3067414656 | Terminating... @173038875
3067414656 | Waiting... @173038875
3067414656 | [No Result] @173038875
Click "Create Server Thread" to start..
3067414656 | Freeing... @173038877
Click "Create Server Thread" to start..
here are the results from the post message test it seems that post message handler is executed in the main thread both in QT and GTK.
« Last Edit: October 31, 2015, 08:31:07 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64