Page 2 of 2

Re: Thread and TCP

PostPosted: Thu Nov 30, 2017 3:08 am
by ingalime
Thank you very much for your help and patience. The new code works as expected and if the server is turned ON and OFF. All perfectly! Please check the new version:
Main:
Code: Select all
TFormMenu *FormMenu;
TMyConnect * MyConnect = NULL;
extern String ip;
extern int port;
int chek = 0;
//---------------------------------------------------------------------------
__fastcall TFormMenu::TFormMenu(TComponent* Owner)
   : TForm(Owner)
{
}
//---------------------------------------------------------------------------
//This button if user want just close form
void __fastcall TFormMenu::Button1Click(TObject *Sender)
{
 chek = 1;
 Close();
}
//---------------------------------------------------------------------------
void __fastcall TFormMenu::ThreadTerminated(TObject *Sender)
{
   TMyConnect *Thread = static_cast<TMyConnect*>(Sender);
   if(Thread->FatalException)//if setver OFF=Connect timed out.
    {
     chek = 1;
     //user should not see messages in English
     //in the future in my language:
     ShowMessage(L"Sorry there is no connection to the server");
    }

   Button2->Enabled = true;
   AniIndicator1->Visible = false;
   Close();
}
//---------------------------------------------------------------------------
void __fastcall TFormMenu::Button2Click(TObject *Sender)
{
  if(Memo1->Lines->Count > 0)
   {
   Button2->Enabled = false;
   AniIndicator1->Visible = true;
   MyConnect = new TMyConnect(ip, port, Memo1->Lines);
    MyConnect->OnTerminate = &ThreadTerminated;
   MyConnect->Start();
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMenu::FormShow(TObject *Sender)
{
 chek = 0;
}
//---------------------------------------------------------------------------

void __fastcall TFormMenu::FormClose(TObject *Sender, TCloseAction &Action)
{
  if(chek == 0)
      {
      //in the future in my language:
      ShowMessage(L"Thank you. All good.");
       
      }
}
//---------------------------------------------------------------------------


h. TThread
Code: Select all
class TMyConnect : public TThread
{
   private:
      String FHost;
      Word FPort;
      TStringList *FLines;
   protected:
      void __fastcall Execute();
   public:
      __fastcall TMyConnect(String AHost, Word APort, TStrings *ALines);
      __fastcall ~TMyConnect();
};


cpp. TThread
Code: Select all
__fastcall TMyConnect::TMyConnect(String AHost, Word APort, TStrings *ALines)
    : TThread(true), FHost(AHost), FPort(APort)
{
   FreeOnTerminate = true;
   FLines = new TStringList;
   FLines->Assign(ALines);
}
//---------------------------------------------------------------------------

__fastcall TMyConnect::~TMyConnect()
{
  delete FLines;
}
//---------------------------------------------------------------------------
void __fastcall TMyConnect::Execute()
{
   std::unique_ptr<TIdTCPClient> Client(new TIdTCPClient);

   Client->Host = FHost;
   Client->Port = FPort;
   Client->ConnectTimeout = 5000;

   Client->Connect();
   Client->IOHandler->Write(FLines, true, IndyTextEncoding_UTF8());
   Client->Disconnect();
}


I love Indy!

Re: Thread and TCP

PostPosted: Thu Jan 04, 2018 4:03 am
by Lena
Thank you very much for sharing the code. I copied this code into my project.

Re: Thread and TCP

PostPosted: Thu Jan 11, 2018 6:01 am
by Lena
Hi.
Is the use of thread safe ShowMessage in ThreadTerminated?

Re: Thread and TCP

PostPosted: Thu Jan 11, 2018 2:23 pm
by rlebeau
Lena wrote:Is the use of thread safe ShowMessage in ThreadTerminated?


As I stated earlier in this discussion:

Remy wrote:To update your UI when the thread is finished, use the thread's OnTerminate event, which is synchronized with the main UI thread


So yes, it is safe to do things with the UI in the OnTerminate event, including popup dialogs.

Re: Thread and TCP

PostPosted: Fri Jan 19, 2018 3:28 am
by Lena
OK. And one more question. I want to save the data to the database:
Code: Select all
 String TABLE, VREMYA, SOSTAV;
//***
      DataModule1->FDQueryInsertCheck->Active = false;
      DataModule1->FDQueryInsertCheck->ParamByName(L"timestring")->AsString = VREMYA;
//***
               DataModule1->FDQueryInsertCheck->ExecSQL();


Where to place this code correctly?
In:
void __fastcall TFormPrint::IdTCPServer1Execute(TIdContext *AContext)
or in:
void __fastcall TUpdateRichEdit::DoNotify()

?

Re: Thread and TCP

PostPosted: Tue Jan 23, 2018 11:57 am
by rlebeau
Lena wrote:Where to place this code correctly?


Wherever you want.

Personally, I use database connections on TDataModule objects inside of worker threads all the time, and do not sync them with the main UI thread at all. Works fine for me. But it does help to make sure that you are:

- using thread-safe DB components, or at least don't access DB components across thread boundaries.

- a thread-safe DB driver

- giving each worker thread its own DB connection (or at least use a connection pool), don't share a connection across multiple threads at the same time.

In some of my projects, I have a dedicated TDataModule per thread.

In other projects, I have a pool of TSQLConnection objects, from which each thread pulls out a connection on demand when needed and puts it back in the pool when done. I then create TSQLQuery and TSQLStoredProc objects dynamically as needed, using whichever TSQLConnection has been obtained from the pool.

Re: Thread and TCP

PostPosted: Thu Feb 08, 2018 3:12 am
by Lena
Thank you very much for the clarification!