Page 1 of 1

Thread synchronization and GUI

PostPosted: Thu Feb 28, 2019 1:40 am
by mark_c
Hello,
I'm struggling with an old educational project for the study of synchronization, I do not understand why in this case there is no collision!
In my opinion, it should be there when Thread1 writes to the StringGrid: am I wrong?

Thank you
Code: Select all
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

class TMyThread1 : public TThread
{
protected:
   void __fastcall Execute();
public:
   __fastcall TMyThread1();
   void __fastcall MySincrSock1();
   String msg;
};

TMyThread1 *Thread1 = NULL;


//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
   ServerSocket1->Port = 5000;
   ServerSocket1->Active = true;
}
//---------------------------------------------------------------------------

__fastcall TMyThread1::TMyThread1()
: TThread(true)
{
}
//---------------------------------------------------------------------------

void __fastcall TMyThread1::MySincrSock1()
{
   try{
      for(int actconn = 0; actconn < Form1->ServerSocket1->Socket->ActiveConnections; actconn++)
      {
         Form1->ServerSocket1->Socket->Connections[actconn]->SendText(msg);
         Form1->Caption="1";
      }

   } catch(...) { }
}
//---------------------------------------------------------------------------

void __fastcall TMyThread1::Execute()
{
   while (!Terminated)
   {
      for(int i=0; i<10;i++)
      {
         msg.sprintf("Y27.5,1,192.168.1.%d,5694,25,25,127",i);
         Synchronize(&MySincrSock1);

                        Form1->StringGrid1->Cells[1][i]=msg;
         Sleep(100);
         Form1->StringGrid1->Cells[1][i]="";
      }
   }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
   delete Thread1;

   ServerSocket1->Active = false;
       
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   Thread1 = new TMyThread1();

   Button1->Enabled = false;
   Button2->Enabled = true;

   Caption = "Started.....";

   Thread1->Resume();       
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
   if (Thread1) Thread1->Terminate();

   Button1->Enabled = true;
   Button2->Enabled = false;

   Caption = "Stopped.....";       
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket1ClientError(TObject *Sender,
      TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
   Socket->Close();
   ErrorCode = 0;       
}
//---------------------------------------------------------------------------

Re: Thread synchronization and GUI

PostPosted: Fri Mar 01, 2019 2:59 am
by mark_c
finally with this version I can experience a collision: apparently a single thread, the previous version of the code, is not enough to cause a collision or, it can happen a collision but in a non-deterministic time

Code: Select all
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

class TMyThread1 : public TThread
{
protected:
   void __fastcall Execute();
public:
   __fastcall TMyThread1();
   void __fastcall MySincrSock1();
   String msg;
};


class TMyThread2 : public TThread
{
protected:
   void __fastcall Execute();
public:
   __fastcall TMyThread2();
   void __fastcall MySincrSock2();
   String msg;
};

TMyThread1 *Thread1 = NULL;
TMyThread2 *Thread2 = NULL;

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
   ServerSocket1->Port = 5000;
   ServerSocket1->Active = true;

   ServerSocket2->Port = 5001;
   ServerSocket2->Active = true;
}
//---------------------------------------------------------------------------

__fastcall TMyThread1::TMyThread1()
: TThread(true)
{
}
//---------------------------------------------------------------------------

__fastcall TMyThread2::TMyThread2()
: TThread(true)
{
}
//---------------------------------------------------------------------------

void __fastcall TMyThread1::MySincrSock1()
{
   try{
      for(int actconn = 0; actconn < Form1->ServerSocket1->Socket->ActiveConnections; actconn++)
      {
         Form1->ServerSocket1->Socket->Connections[actconn]->SendText(msg);
         Form1->Caption="1";
      }

   } catch(...) { }
}
//---------------------------------------------------------------------------

void __fastcall TMyThread2::MySincrSock2()
{
   try{
      for(int actconn = 0; actconn < Form1->ServerSocket2->Socket->ActiveConnections; actconn++)
      {
         Form1->ServerSocket2->Socket->Connections[actconn]->SendText(msg);
         Form1->Caption="2";
      }

   } catch(...) { }
}
//---------------------------------------------------------------------------

void __fastcall TMyThread1::Execute()
{
   while (!Terminated)
   {
      for(int i=0; i<10;i++)
      {
         msg.sprintf("Y27.5,1,192.168.1.%d,5694,25,25,127",i);
         Synchronize(&MySincrSock1);

                        Form1->StringGrid1->Cells[1][i]=msg;
         Sleep(100);
         Form1->StringGrid1->Cells[1][i]="";
      }
   }
}
//---------------------------------------------------------------------------

void __fastcall TMyThread2::Execute()
{
   while (!Terminated)
   {
      for(int i=0; i<10;i++)
      {
         msg.sprintf("Y27.5,1,192.168.1.%d,5694,25,25,127",i);
         Synchronize(&MySincrSock2);

                        Form1->StringGrid1->Cells[1][i]=msg;
         Sleep(100);
         Form1->StringGrid1->Cells[1][i]="";
      }
   }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
   delete Thread1;
        delete Thread2;

   ServerSocket1->Active = false;
        ServerSocket2->Active = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   Thread1 = new TMyThread1();
        Thread2 = new TMyThread2();

   Button1->Enabled = false;
   Button2->Enabled = true;

   Caption = "Started.....";

   Thread1->Resume();
        Thread2->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
   if (Thread1) Thread1->Terminate();
        if (Thread2) Thread2->Terminate();

   Button1->Enabled = true;
   Button2->Enabled = false;

   Caption = "Stopped.....";       
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket1ClientError(TObject *Sender,
      TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
   Socket->Close();
   ErrorCode = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket2ClientError(TObject *Sender,
      TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
   Socket->Close();
   ErrorCode = 0;
}
//---------------------------------------------------------------------------

Re: Thread synchronization and GUI

PostPosted: Sat Mar 09, 2019 12:17 pm
by mark_c
Hello,
but is it possible to declare and implement the shared methods only once so they can be used by multiple threads?

the method below, for example, is very inconvenient.

Code: Select all
class TMyThread1 : public TThread
{
protected:
   void __fastcall Execute();
public:
   __fastcall TMyThread1();
   void __fastcall MySincrSock();
        void __fastcall MyStringGrid();
   String msg;
        int i;
};


class TMyThread2 : public TThread
{
protected:
   void __fastcall Execute();
public:
   __fastcall TMyThread2();
   void __fastcall MySincrSock();
        void __fastcall MyStringGrid();
   String msg;
        int i;
};

void __fastcall TMyThread1::MyStringGrid()
{
        Form1->StringGrid1->Cells[1][i]=msg;
        if(i > 0)
        Form1->StringGrid1->Cells[1][i-1]="";
}
//---------------------------------------------------------------------------

void __fastcall TMyThread2::MyStringGrid()
{
        Form1->StringGrid1->Cells[1][i]=msg;
        if(i > 0)
        Form1->StringGrid1->Cells[1][i-1]="";
}
//---------------------------------------------------------------------------

[b]void __fastcall TMyThread(n)::MyStringGrid()[/b]
{
        Form1->StringGrid1->Cells[1][i]=msg;
        if(i > 0)
        Form1->StringGrid1->Cells[1][i-1]="";
}
//---------------------------------------------------------------------------