Lazarus

Programming => Widgetset => Cocoa => Topic started by: Shebuka on July 26, 2019, 07:14:12 pm

Title: ShowMessage is blocking code execution
Post by: Shebuka on July 26, 2019, 07:14:12 pm
Hello,
with LCLCarbon I was able to show the message dialog and move forward with my code. Both ShowMessage(AText); and MessageDlg(AText, mtInformation, [mbOK], 0); were not blocking the main thread. With LCLCocoa all dialogs created from Dialog unit are blocking the main thread. Is this a bug? Am I doing something wrong?


p.s. For workaround this issue I've ended up creating this:

Code: Pascal  [Select][+][-]
  1. procedure TBigBoss.ShowMessageToUserInDialog(AText: String);
  2. var
  3.   DlgFrm: TForm;
  4.   CurButton: TBitBtn;
  5.   i: Integer;
  6. begin
  7.   if AText = '' then
  8.     exit;
  9.  
  10.   DlgFrm := CreateMessageDialog(AText, mtInformation, [mbOK]);
  11.  
  12.   for i := 0 to DlgFrm.ComponentCount-1 do
  13.   begin
  14.     if (DlgFrm.Components[i] is TBitBtn) then
  15.     begin
  16.       CurButton := TBitBtn(DlgFrm.Components[i]);
  17.       CurButton.OnClick := @CloseShowMessageToUserInDialog;
  18.     end;
  19.   end;
  20.  
  21.   DlgFrm.Show;
  22. end;    
  23.  
  24. procedure TBigBoss.CloseShowMessageToUserInDialog(Sender: TObject);
  25. begin
  26.   TForm(TBitBtn(Sender).Parent).Close;
  27. end;

any suggestions?
Title: Re: ShowMessage is blocking main thread
Post by: skalogryz on July 26, 2019, 09:39:35 pm
Both ShowMessage(AText); and MessageDlg(AText, mtInformation, [mbOK], 0); were not blocking the main thread. With LCLCocoa all dialogs created from Dialog unit are blocking the main thread. Is this a bug? Am I doing something wrong?
Both ShowMessage (https://lazarus-ccr.sourceforge.io/docs/lcl/dialogs/showmessage.html) and MessageDlg (https://lazarus-ccr.sourceforge.io/docs/lcl/dialogs/messagedlg.html) are not blocking the main thread, they're calling modal dialogs.
"Modal" means that the code, following the call to either function would only proceed after the dialog is closed (it's not "a thread blocking" in any manner).

If Carbon didn't show them in modal mode, then it's a LCLCarbon bug.

Your workaround is just fine.
Title: Re: ShowMessage is blocking main thread
Post by: Shebuka on August 05, 2019, 05:26:54 pm
Both ShowMessage(AText); and MessageDlg(AText, mtInformation, [mbOK], 0); were not blocking the main thread. With LCLCocoa all dialogs created from Dialog unit are blocking the main thread. Is this a bug? Am I doing something wrong?
Both ShowMessage (https://lazarus-ccr.sourceforge.io/docs/lcl/dialogs/showmessage.html) and MessageDlg (https://lazarus-ccr.sourceforge.io/docs/lcl/dialogs/messagedlg.html) are not blocking the main thread, they're calling modal dialogs.
"Modal" means that the code, following the call to either function would only proceed after the dialog is closed (it's not "a thread blocking" in any manner).

If Carbon didn't show them in modal mode, then it's a LCLCarbon bug.

Your workaround is just fine.

ShowMessage(AText); must NOT be a modal dialog, it doesn't require a modal input and doesn't need a modal choice reply (in fact, it's a procedure). So LCLCarbon's behaviour is kinda correct.

I'm perfectly aware of modal dialogs and sheets in Cocoa and I'm using them regularly, it will be perfect to be able to use LCLCocoa dialogs with similar delegate/block pattern (like assigning a function to 'mbOKDelegate' property of the dialog to be called when mbOK is pressed) and not block the code execution.

just a thought: If the code is blocked behind the modal window, and the code is running on main thread 0, then from my code perspective the main thread 0 is blocked... What happens behind curtains is interesting but not relevant to the question above.
Title: Re: ShowMessage is blocking code execution
Post by: lucamar on August 05, 2019, 06:13:27 pm
Most* dialogs, including ShowMessage, are modal in most/all widgetsets. Even if they "return" nothing, like ShowMessage

If you want a modeless ShowMessage you'll have to build it yourself, I fear. It's not very difficult, though.

Whether the behaviour of ShowMessage in Carbon shold be considered a bug, a widgetset quirk or "how-it-should-be" is a question I'll leave to deeper minds than mine :)


* Notable, but logical, exceptions are TFindFialog and TReplaceDialog
Title: Re: ShowMessage is blocking main thread
Post by: skalogryz on August 05, 2019, 10:12:23 pm
just a thought: If the code is blocked behind the modal window, and the code is running on main thread 0, then from my code perspective the main thread 0 is blocked... What happens behind curtains is interesting but not relevant to the question above.
Actually the only things "blocked" are input process (keyboard and the mouse...) and the execution of the code that follows ShowMessage();
So the main thread is not blocked at all.

Anything else: Timers, Paint events, Custom Events (i.e. sent from a separate thread) as still being processed by the Main thread.

Potentially, if ShowMessage is shown due to one of this reoccurring events, you might end up with a pretty unpleasant message boxes overflow or worse.
Title: Re: ShowMessage is blocking code execution
Post by: MISV on August 06, 2019, 01:14:43 am
Maybe see:
https://stackoverflow.com/questions/1256963/if-messagebox-related-are-synchronous-why-doesnt-my-message-loop-freeze

If I understand it correctly - no particular knowledge on this subject beyond casual usage - it is essentially recursive message loops

1) main window message loop function acts on some event which triggers code that opens a message window
2) this instantiates a new message loop function in the message window handling messages
3) keyboard etc. stuff is grabbed, but paint is also passed on by calling main window wndproc function
4) this continues until a message comes that will lead to message window to be closed soon (e.g. button click on "ok")
5) this in turn posts a message back to message window message loop that we are closing form
6) this exits the message window message loop and we move through callstack back to continue from #1



Title: Re: ShowMessage is blocking code execution
Post by: Shebuka on September 12, 2019, 12:49:33 pm
If you want a modeless ShowMessage you'll have to build it yourself, I fear. It's not very difficult, though.

That's what I've kinda done with my workaround

Whether the behaviour of ShowMessage in Carbon shold be considered a bug, a widgetset quirk or "how-it-should-be" is a question I'll leave to deeper minds than mine :)

My second post was more about opening a dialogue (pun intended) about "how-it-should-be". ShowMessage can be easily a non-modal form, and if you need modal there is a MessageDlg. Even name suggests that one is like showing something to the user and the other is a modal question/information to the user.

I also understand that this is a complex subject and changing the behaviour of ShowMessage can impact software that relies on the modality of it...

Referring to my second post, once you call CreateMessageDialog the code already created all the buttons. So we can add a GetButton method and my current workaround becomes a legit system provided non-modal ShowMessage (without the need of "build-it-yourself")?

Then we can do:
Code: Pascal  [Select][+][-]
  1. var:
  2.   TBitBtn: OKButton;
  3.  
  4. DlgFrm := CreateMessageDialog(AText, mtInformation, [mbOK]);
  5.  
  6. OKButton := DlgFrm.GetButton(mbOK);
  7. if (OKButton <> nil) then
  8.   OKButton.OnClick := @CloseShowMessageToUserInDialog;
TinyPortal © 2005-2018