1

When i used this code with button, it is ok... All sockets connected success. All events working. no problem (OnSessionClosed, OnSessionConnected, ...)

procedure TfrmMain.btnConnectClick(Sender: TObject);
var
  I: Integer;
begin    
  for I := 0 to query.RecordCount - 1 do
  begin
    pUser[I] := TUser.Create();
    pUser[I].Connect(frmMain.editEbenezerIP.Text);
    pUser[I].run := False;
    pUser[I].username := Trim(query.FieldByName('strAccountID').Text);
    pUser[I].password := Trim(query.FieldByName('strPasswd').Text);
    pUser[I].md5 := editMD5.Text;
    pUser[I].Resume;
    query.Next;
  end;
end;

i created a thread to connect with sleep. (my thread TConnector). All thread connected but OnSessionConnected event not working when i created with TConnector.

No problem with button to use create sockets.

procedure TUser.OnSessionConnected(Sender: TObject; ErrCode: Word);
begin
     ShowMessage('Connection success!');
end;

procedure TUser.Connect(eip : string);
begin
  Initialize;
  socket := TWSocket.Create(nil);
  socket.OnDataAvailable    := OnDataAvailable;
  socket.OnSessionConnected := OnSessionConnected;
  socket.OnSessionClosed    := OnSessionClosed;
  socket.Connect;
end;

procedure TConnector.Execute;
var
  I : Integer;
  pUser : array [0..1500] of TUser;
begin
  for I := 0 to frmMain.query.RecordCount - 1 do
  begin
    pUser[I] := TUser.Create();
    pUser[I].run := False;
    pUser[I].username := Trim(frmMain.query.FieldByName('strAccountID').Text);
    pUser[I].password := Trim(frmMain.query.FieldByName('strPasswd').Text);
    pUser[I].Connect(frmMain.editEbenezerIP.Text);
    pUser[I].Resume;
    frmMain.query.Next;
    **Sleep(100);**
  end;
end;

I fixed this problem with Synchronize(CreateUser);. Thanks for your answers

  TConnector = class(TThread)
  private

  protected
    procedure Execute; override;
  public
    strAccountID, strPasswd, MD5, eIP : string;
    X : Integer;
    constructor Create;
    procedure CreateUser;
  end;

procedure TConnector.CreateUser;
begin
    Output(Format('Thread for %s',[strAccountID]));
    frmMain.pUser[X] := TUser.Create();
    frmMain.pUser[X].run := False;
    frmMain.pUser[X].username := strAccountID;
    frmMain.pUser[X].password := strPasswd;
    frmMain.pUser[X].md5 := MD5;
    frmMain.pUser[X].Connect(eIP, frmMain);
    frmMain.pUser[X].Resume;

end;

procedure TConnector.Execute;
var
   I : Integer;
begin
  MD5          := frmMain.editMD5.Text;
  eIP          := frmMain.editEbenezerIP.Text;
  for I := 0 to frmMain.query.RecordCount - 1 do
  begin
    X := I;
    strAccountID := Trim(frmMain.query.FieldByName('strAccountID').Text);
    strPasswd    := Trim(frmMain.query.FieldByName('strPasswd').Text);

    **Synchronize(CreateUser);**

    Sleep(1000);
    frmMain.query.Next;
  end;

  while(not Terminated)do
  begin
    Sleep(1000);
    OutPut('test');
  end;
end;

1 Answer 1

1

TWSocket uses a non-blocking socket and a hidden window for handling socket state updates asynchronously. As such, you need to give your thread a message loop. It works in a TButton.OnClick event because it is utilizing the main thread's existing message loop.

Edit: The simplest message loop involves calling Peek/GetMessage(), TranslateMessage(), and DispatchMessage() in a loop for the lifetime of the thread, so you need to add those function calls to your worker thread, eg:

procedure TConnector.Execute;
var
  I : Integer;
  pUser : array [0..1500] of TUser;
  Msg: TMsg
begin
  for I := 0 to frmMain.query.RecordCount - 1 do
  begin
    if Terminated then Break;
    pUser[I] := TUser.Create();
    pUser[I].run := False;
    pUser[I].username := Trim(frmMain.query.FieldByName('strAccountID').Text);
    pUser[I].password := Trim(frmMain.query.FieldByName('strPasswd').Text);
    pUser[I].Connect(frmMain.editEbenezerIP.Text);
    pUser[I].Resume;
    frmMain.query.Next;
  end;

  while (GetMessage(Msg, 0, 0, 0) > 0) and (not Terminated) then
  begin
    TranslateMessage(msg);
    DispatchMessage(msg);
  end;

  // perform cleanup here as needed...
end;

procedure TConnector.Stop;
begin
  Terminate;
  PostThreadMessage(ThreadID, WM_QUIT, 0, 0);
end;
Sign up to request clarification or add additional context in comments.

4 Comments

Can you explain with example?
Next time, please try to do some research yourself, there is TONS of information available about message queues and message loops.
Thanks remy my problem fixed with Synchronize.
You are using Synchronize() to force your sockets to run in the main thread where they don't belong. That is not the best solution. Either give the worker threads their own message loops so the non-blocking sockets will work in the worker threads, or else switch to blocking sockets so you not have to deal with message loop issues anymore.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.