How correct

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Post Reply
ingalime
Top Poster
Top Poster
Posts: 29
Joined: Wed Apr 12, 2017 3:22 am

How correct

Post by ingalime »

How much more correct?

Code: Select all

//FMX project
try
   {
      SpeedButton1->Enabled = false;
      Application->ProcessMessages();
      //other code
  
   }
   __finally
       {
	  SpeedButton1->Enabled = true;
        }

or

Code: Select all

//FMX project
SpeedButton1->Enabled = false;
Application->ProcessMessages();
try
   {

      //other code
  
   }
   __finally
       {
	  SpeedButton1->Enabled = true;
        }

rlebeau
BCBJ Author
BCBJ Author
Posts: 1716
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: How correct

Post by rlebeau »

Neither. It should be more like this instead:

Code: Select all

SpeedButton1->Enabled = false;
try
{
    Application->ProcessMessages();
    //other code 
}
__finally
{
    SpeedButton1->Enabled = true;
}
On the other hand, why are you calling ProcessMessages() at all? That is generally a sign of bad code design. If you need to let the UI process activity periodically, you should break up the code so that flow returns to the main message loop naturally, for example:

Code: Select all

void __fastcall TMyForm::StartDoingSomething()
{
    SpeedButton1->Enabled = false;

    // some code...

    // let the main thread breathe a little! ...
    TThread::ForceQueue(nullptr, DoMoreOfSomething);
}

void __fastcall TMyForm::DoMoreOfSomething()
{
    // some more code...
    SpeedButton1->Enabled = true;
}
Or:

Code: Select all

void __fastcall TMyForm:StartDoingSomething()
{
    SpeedButton1->Enabled = false;

    // some code...

    // let the main thread breathe a little! ...
    TThread::ForceQueue(nullptr,
        [this]()
        {
            // some more code...
            SpeedButton1->Enabled = true;
        }
    );
}
Remy Lebeau (TeamB)
Lebeau Software
ingalime
Top Poster
Top Poster
Posts: 29
Joined: Wed Apr 12, 2017 3:22 am

Re: How correct

Post by ingalime »

On the other hand, why are you calling ProcessMessages() at all?
I want the user not to be able to press the button twice, three times ...
Without this line of code Application->ProcessMessages, the button appears to be accessible.
My code is taken from this forum:

Code: Select all

//send Email
bool __fastcall OpenURL5(const String &AURL)
{

   _di_NSURL NSU = StrToNSUrl(AURL);
	if (SharedApplication()->canOpenURL(NSU))
        return SharedApplication()->openURL(NSU);
    else
		return false;

}

//---------------------------------------------------------------------------

void __fastcall TFormAkc::Button1Click(TObject *Sender)
{
  String SenderName = Trim(Edit1->Text);
   if (SenderName.IsEmpty())
   {
     ShowMessage(_D("Please enter your Name."));
      Edit1->SetFocus();
      return;
   }

  Button1->Enabled = false;//now advice from rlebeau
   try
   {

	  Application->ProcessMessages(); //now advice from rlebeau
	  String ToStr = _D("My email...");
	  String SubjectStr = _D("Participate in promotions");
	  String BodyStr = _D("Nickname: ") + Trim(Edit1->Text) +
		 _D(";  Your code: ") + Trim(Edit2->Text);

	  SubjectStr = TIdURI::ParamsEncode(SubjectStr);
      BodyStr = TIdURI::ParamsEncode(BodyStr);

      String URL = _D("mailto:") + ToStr + _D("?subject=") + SubjectStr + _D("&body=") + BodyStr;

	  if (!OpenURL5(URL))
      {
         ShowMessage(_D("Unable to sent. Please check the Internet connection, and make sure an email client is installed."));
         return;
      }

      ShowMessage(_D("Thank You!"));
   }
   __finally
   {
	  Button1->Enabled = true;
   }
}
//---------------------------------------------------------------------------


Please explain to me also what is the difference: ForceQueue and TTask? Can I do this?:

Code: Select all

  Button1->Enabled = false;
 	TTask::Run([this]()
	 {
         //send email
         //****
	 }

	);
      Button1->Enabled = true;
}
//---------------------------------------------------------------------------
rlebeau
BCBJ Author
BCBJ Author
Posts: 1716
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: How correct

Post by rlebeau »

ingalime wrote:I want the user not to be able to press the button twice, three times ...
They won't be able to, once you have disabled it.
ingalime wrote:Without this line of code Application->ProcessMessages, the button appears to be accessible.
If it is just a matter of visual appearance, simply use the button's Update() (VCL) or Repaint() (FMX) method instead, eg:

Code: Select all

Button1->Enabled = false;
Button1->Update();
...

Code: Select all

Button1->Enabled = false;
Button1->Repaint();
...
Absolutely stay away from Application->ProcessMessages()!
ingalime wrote: Please explain to me also what is the difference: ForceQueue and TTask?
TThread::ForceQueue() can be used directly in the main UI thread to post an asynchronous operation for the main message queue to run at a later time. The operation will be executed when the message queue gets to it. No worker thread is used for this.

TTask runs an operation in a separate worker thread.
ingalime wrote: Can I do this?
Since TTask runs in a separate thread, you would be re-enabling the Button before the task has finished (or even before the task has started running). You would need to use TThread::Synchronize() or TThread::Queue() inside the task lambda instead, eg:

Code: Select all

Button1->Enabled = false;
TTask::Run(
    [this]()
    {
        try
        {
            // send email ...
        }
        __finally
        {
            TThread::Queue(nullptr,
                [this](){ Button1->Enabled = true; }
            );
        }
    }
);
Remy Lebeau (TeamB)
Lebeau Software
ingalime
Top Poster
Top Poster
Posts: 29
Joined: Wed Apr 12, 2017 3:22 am

Re: How correct

Post by ingalime »

Thanks.
But not fully understood.

Code: Select all

class T: public TThread
private:
  void __fastcall Log(void);
protecteded:
  void __fastcall Execute();
public:
  __fastcall T(bool CreateSuspended);

//cpp
void __fastcall T::Execute()
{
//code 
Synchronize(Log);
}

void __fastcall T::Log()
{
 Memo1->Items->Add(L"Log1...");
}
And:

Code: Select all

void __fastcall TMyForm:StartDoingSomething()
{

//code
    TThread::ForceQueue(nullptr,
        [this]()
        {
            
             Memo1->Items->Add(L"Log1...");
        }
    );
}
Which is more correct Synchronize or ForceQueue?
rlebeau
BCBJ Author
BCBJ Author
Posts: 1716
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:

Re: How correct

Post by rlebeau »

ingalime wrote:But not fully understood.
...
Which is more correct Synchronize or ForceQueue?
You are comparing apples and oranges. Neither one is "more correct" than the other. They are two different scenarios. One is threaded, the other is not. Use whichever one suits your needs.
Remy Lebeau (TeamB)
Lebeau Software
Post Reply