Encapsulate Tclientsocket connections in Multithreads

Asked

Viewed 876 times

4

I have a variable number X of electronic equipment (Weather stations) in my local network, each equipment provides a Serversocket connection with an IP and a specific Port, I have an application developed in DELPHI XE5 that connects to all these equipment, my application knows what are the Ips and Ports of this equipment, because they are registered in the database, when opening my application, I dynamically create a connection [Tclientsocket (Array)] for each of these equipment, to which later I change a lot of information, like a conversation, I ask the temperature of all the equipment and they answer me, or I can ask the temperature for one of them, the humidity for another, the wind speed for another etc... through internal OPERATIONS.

Today I do a FOR loop of all the connected equipment and from this I know which operation with the equipment my software is and then I do the conversation randomly with each equipment, but this is slow, because as the number of equipment increases, Slows down the FOR. What I want to do is a Thread to eliminate FOR, I’d like to know if that’s possible. The events onConnect, Onread, etc... of my Tclientscojet are assigned in the creation of the Tclientsocket Array, so I end up having this wait of one to use, then the other and I cannot meet all the equipment at the same time.

I wish I could use Thread for this and meet all equipment at the same time, but I don’t know the concept and use.

[UPDATED]

Full source link, I did not post here because it passes a thousand lines:

https://mega.co.nz/#! bAVBwTAb! fdzyS9ENPMWul3wC8GFkKATiJ7whKB7Xzgo5FUHlD6M

Today I use this class I created extended from Tclientsocket:

type
  TTermoCenter = class(TClientSocket)
  private
    countSema: Thandle;
    access: TCriticalSection;
    ...
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Push(inObject: TPalavra; priority: Integer); virtual;
    function Pop(pResObject: pObject; timeout: Integer): Boolean;
  end;

Here is the constructor:

constructor TTermoCenter.Create(AOwner: TComponent);
var
  I: Integer;
begin
  inherited;
  access := TCriticalSection.Create;
  ...
end;

Here is the destructor:

destructor TTermoCenter.Destroy;
var
  I: Integer;
begin
  ...
  access.Free;
  closeHandle(countSema);
  inherited;
end;

variable declaration:

var
  termocenters: array of TTermoCenter;

When creating my Form, I set the size of my Array

SetLength(termocenters, dm.sqlTermocenter.RecordCount);

And I create my connections based on what’s in the database: var Sockettmp: Ttermocenter;

  while not cds.Eof do
  begin
    SocketTmp := TTermoCenter.Create(nil);
    SocketTmp.name := 'cdsNome';
    SocketTmp.Port := 'cdsPorta';
    SocketTmp.ClientType := ctNonBlocking;
    SocketTmp.Host := 'cdsIP';
    // atribui eventos
    SocketTmp.OnRead := TCPRead;
    SocketTmp.OnConnect := TCPConnect;
    SocketTmp.OnDisconnect := TCPDisconnect;
    SocketTmp.OnError := TCPError;

    //Coloca no Array
    termocenters[I] := SocketTmp;
    try
      termocenters[I].Active := True;
      sleep(1000);
    except
      on E: Exception do
        frmMain.mmErros.Lines.Add(TimeToStr(now) + ' - ' + E.ClassName + ' CriaConexao : ' + E.Message);
        end;
      end;
    end;
  cds.Next;
end;
end;

This is a well summarized code of what I have today, I would like a help to implement Threads.

  • Even with threads you will still need a for, I believe. However, connections will be made in parallel. I don’t know anything about Delphi, but I hope you get good answers.

  • From what I understand, I can identify two needs in this question: a) Concept and use of threads in Delphi. b) Implement in this system the use threads for parallel communication with weather stations. For item "a", I recommend this article: http://devutils.blogspot.com/2009/01/threads-conceito-e-exemplo.html. For item "b", I recommend trying the implementation from reading the article and then posting here the difficulties encountered. Makes sense?

  • @Caffe makes perfect sense, this is what I want.

  • Follow the complete source https://mega.co.nz/#! bAVBwTAb! fdzyS9ENPMWul3wC8GFkKATiJ7whKB7Xzgo5FUHlD6M

  • 1

    Which version of Delphi you are using, in XE7 there are many thread facilitators. You should break your question into several specific questions. "If anyone knows how I can improve this code, I am very grateful." , threading is a complex concept that involves various theories and rules, do not ask for the code ready, you should go trying and posting questions to every demand for questions. For starters read these articles. Note: It is in English.

  • 2

    @Alexschmitt My previous comment exposes the mechanics of Stackoverflow. You need to make the question more specific. Note that I am not the only one to know this mechanics (obvious and fortunately) so that your question was suspended by the community. Feel invited to participate in Stackoverflow whenever you feel it is valid to work according to the community (which does not treat individuals but questions and answers).

Show 1 more comment

1 answer

3

I will agree with @Pagenotfound that your question is very broad and awaiting a functional code.

I can give you a few steps to guide. Follow an example using Generics, Annonymous Methods and an anonymous Thread resource:

The idea is to have a connection pool and have a method that creates a Worker thread for each connection to perform a specific task

interface

uses
  System.Generics.Collections, Datasnap.Win.SConnect;

type
  TPoolConexoes = class(TObjectList<TSocketConnection>)
  private
    procedure SeuMetodoQueUsaConexao(const aConexao: TSocketConnection);
  public
    function NewConnection: TSocketConnection;
    function ObterConexoesPorStatus(const aStatus: string): TPoolConexoes;

    procedure ExecutarSeuMetodoParaLista(const Conexoes: TPoolConexoes);
  end;

implementation

uses
  System.Classes;

{ TPoolConexoes }

procedure TPoolConexoes.ExecutarSeuMetodoParaLista(const Conexoes: TPoolConexoes);
var
  conexao: TSocketConnection;
  threadAtual: TThread;
begin
  for conexao in Conexoes do
  begin
    threadAtual := TThread.CreateAnonymousThread(
      procedure
      begin
        Self.SeuMetodoQueUsaConexao(conexao);
      end
    );
    threadAtual.FreeOnTerminate := True;
    threadAtual.Start;
  end;

end;

function TPoolConexoes.NewConnection: TSocketConnection;
var
  conexaoTemp: TSocketConnection;
begin
  conexaoTemp := TSocketConnection.Create(nil);
  Self.Add(conexaoTemp);
  Result := conexaoTemp;
end;

function TPoolConexoes.ObterConexoesPorStatus(const aStatus: string): TPoolConexoes;
begin
  //sua logica aqui
end;

procedure TPoolConexoes.SeuMetodoQueUsaConexao(const aConexao: TSocketConnection);
begin
  //usa a conexao para fazer algo
end;

end.

You can still put all the created threads into a Threadlist and manage the end of them

Or you can extend the thread class to contain the execution code instead of using the Anonimos and keeping the threads in a pool that will run Ondemand

It all depends on your needs

  • Thank you friend, follow the link of Source https://mega.co.nz/#! bAVBwTAb! fdzyS9ENPMWul3wC8GFkKATiJ7whKB7Xzgo5FUHlD6M

Browser other questions tagged

You are not signed in. Login or sign up in order to post.