0

I create a thread

type 
  ss_thread = class;

  ss_thread = class(TThread)
  protected
    Fff_id : string;
    Fff_cmd : string;
    Fff_host : string;
    Fff_port : TIdPort;
    procedure Execute; override;
  public
    constructor Create(const ff_id, ff_cmd: string; ff_host: string; ff_port: TIdPort);
  end;

constructor ss_thread.Create(const ff_id, ff_cmd: string; ff_host: string; ff_port: TIdPort);
begin
  inherited Create(False);
  Fff_id   := ff_id;
  Fff_cmd  := ff_cmd;
  Fff_host := ff_host;
  Fff_port := ff_port;
end;

...
id := 123;
...

nst_ss_thread.Create(id, cmd, host, port);

and doing something on

procedure ss_thread.Execute;
var
  ws : TIdTCPClient;
  data : TIdBytes;
  i : integer;
  list : TList;
begin
      ws := TIdTCPClient.Create(nil);
      ws.Host := Fff_host;
      ws.Port := Fff_port;
....

How to access this thread 'ws' variable thru another thread using id:=123 of thread ?

Thanks

jmp
  • 2,456
  • 3
  • 30
  • 47

2 Answers2

3

It cannot.

You've declared ws as a local variable inside ss_thread.execute, which means it's only visible there. It can't be seen outside ss_thread.execute, even by other parts of ss_thread.

If you want it visible from other places or threads, you need to move it to a more visible scope. For instance, if you want it visible from other places in ss_thread, move it to the interface declaration in private or protected sections, and if you want it visible from outside ss_thread move it to the published or public sections.

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • it's too hard to understand it, what to do to have a list of TIdTCPClient from my threads ? What i did, i store them all on creation into TThreadList, but if thread destroy it i got access violation, thats why i asked about access to thread, maybe some example would be nice. – jmp Nov 27 '12 at 13:36
  • @waza123: Your question asks nothing about having a list of TIdTCPClients. It asks about how to access a local variable outside it's scope of visibility, which is what both Arioch'The and I answered. If you have a different question now, post a new question; don't change the whole meaning of this one after it's been answered. – Ken White Nov 27 '12 at 13:47
  • @waza123 You should not. Indy uses "thread per connection" model and you should not detach connection objects from threads. If you want the pool - then Indy has built-in connection pooling. You don't know how Indy internals would react to it and if that can make some unexpected change in behavior. Also Indy does not scale well due to this design. http://robertocschneiders.wordpress.com/2012/11/22/datasnap-analysis-based-on-speed-stability-tests/ Perhaps u'd better some simplistic blocking components like TWebsocket or Synapse, running in queues in 1..4 threads (1 per CPU) and use Actors Model – Arioch 'The Nov 28 '12 at 09:21
2

You'd better not. Thread objects are exactly made to insulate its variables from other threads.
Otherwise all kind of random non-reproducible errors would appear - http://en.wikipedia.org/wiki/Heisenbug

Parallel programming should have very clear separation and insulation. Because You can never predict the timing of execution and which statement would run earlier and which one later.

Imagine that easy scenario:

  ws := TIdTCPClient.Create(nil);
  ws.Host := Fff_host;
      // at this point another thread gets access to ws variable, 
      // as You demanded - and changes it, so WS gets another value!
  ws.Port := Fff_port;

How would you detect such a bug, if it happens only on client multi-processor computer under heavy load once a month ? In your workstation during debug sessions or simulation it would not be reproduced ever! How would you catch it and fix ?

As a rule of thumb, when doing parallel programming the data should be spleat into "shared immutable" and "private mutable" pieces, and when doing inter-thread communication you should - similar to inter-process communications - make some events/messages queue and pass commands and replies to/from threads, like it is done in Windows GDI or like in MPI

Then you thread would fetch "change ws variable" command from queue - in the proper moment when the change is allowed - and change it from inside. Thus you would assume control and assure that variables are only changed in that point and in that manner, that would not derail the code flow.

I suggest you to read OTL examples to see how inter-thread communication is done in more safe way that direct access to objects. http://otl.17slon.com/tutorials.htm

Arioch 'The
  • 15,799
  • 35
  • 62