我在 TThread 中使用 ipWorks 组件 TipwIPPort 。据我了解,TipwIPPort是非阻塞的。
我熟悉创建线程,其中执行方法中的所有处理都是“阻塞”。
在这种情况下,我需要连接到远程服务器,然后使用 TIpwIPPort.DataToSend 进行后续调用。我在线程的执行函数中调用 Connect 方法。但 OnConnected 事件永远不会被触发。
我需要设置哪些参数和属性(例如,“CreateSuspended”传递给构造函数, FreeOnTerminate 值),以便我可以控制何时终止线程。
type TMyThread=class(TThread)
private
IPPort1: TipwIPPort;
procedure IPPort1Connected(Sender: TObject; StatusCode: Integer; const Description: String);
procedure IPPort1DataIn(Sender: TObject; Text: String; EOL: Boolean);
end;
procedure TMyThread.IPPort1Connected(Sender: TObject; StatusCode: Integer; const Description: String);
begin
// never get here
AppendToLog('Status Code in Connect:'+inttostr(StatusCode)+'; Description:'+Description);
if StatusCode = 0 then begin
// send data to server using ipport1.datatosend.....
end;
end;
procedure TMyThread.Execute;
begin
appendtolog('TMyThread.Execute');
IPPort1 := TipwIPPort.Create(nil);
try
With IPPort1 do begin
EOL := #4;
KeepAlive := True;
OnConnected := IPPort1Connected;
OnDataIn := IPPort1DataIn;
end;
IPPort1.Connect('xxx.xxx.xxx.xxx',8888);
appendtolog('done with execute');
finally
end;
end;
procedure TMyThread.IPPort1DataIn(Sender: TObject; Text: String; EOL: Boolean);
begin
if (Pos('keytoendconnection',Text)>0) then begin
ipPort1.Disconnect;
// Terminate the thread and free
end;
end;
procedure TForm1.Button1Click(sender: TObject);
var
myThread;
begin
// what parameters and properties do I need to set to allow me to control when the thread is terminated???
myThread := TMyThread.Create(True);
mSouthernObject.FreeOnTerminate := False;
mSouthernObject.Resume;
end;
答案 0 :(得分:3)
如果您阅读了IPPort组件的documentation,则说明:
组件的操作几乎完全异步。除处理域名解析的所有呼叫都通过异步消息(无阻塞呼叫)进行操作。与使用阻塞调用相比,性能的提升相当可观。
因此,您的线程需要自己的消息队列/循环来接收和分发这些套接字消息,例如:
type
TMyThread = class(TThread)
private
IPPort1: TipwIPPort;
procedure IPPort1Connected(Sender: TObject; StatusCode: Integer; const Description: String);
procedure IPPort1DataIn(Sender: TObject; Text: String; EOL: Boolean);
protected
procedure Execute; override;
procedure DoTerminate; override;
procedure TerminatedSet; override;
end;
procedure TMyThread.IPPort1Connected(Sender: TObject; StatusCode: Integer; const Description: String);
begin
AppendToLog('Status Code in Connect:'+inttostr(StatusCode)+'; Description:'+Description);
if StatusCode = 0 then begin
// send data to server using ipport1.datatosend.....
end else begin
// start a timer or something to issue WM_CONNECT again after a small delay, say 5-10 seconds at least...
end;
end;
const
WM_CONNECT = WM_APP+1;
procedure TMyThread.Execute;
var
Message: TMsg;
begin
appendtolog('TMyThread.Execute');
IPPort1 := TipwIPPort.Create(nil);
try
IPPort1.EOL := #4;
IPPort1.KeepAlive := True;
IPPort1.OnConnected := IPPort1Connected;
IPPort1.OnDataIn := IPPort1DataIn;
PostThreadMessage(ThreadID, WM_CONNECT, 0, 0);
while not Terminated do
begin
if not GetMessage(Message, 0, 0, 0) then Break;
case Message.Msg of
WM_CONNECT:
begin
IPPort1.Connect('xxx.xxx.xxx.xxx', 8888);
end;
//...
else
TranslateMessage(Message);
DispatchMessage(Message);
end;
end;
finally
IPPort1.Free;
end;
end;
procedure TMyThread.DoTerminate;
begin
appendtolog('done with execute');
inherited;
end;
procedure TMyThread.TerminatedSet;
begin
PostThreadMessage(ThreadID, WM_QUIT, 0, 0);
end;
procedure TMyThread.IPPort1DataIn(Sender: TObject; Text: String; EOL: Boolean);
begin
if Pos('keytoendconnection', Text) > 0 then
begin
ipPort1.Disconnect;
Terminate;
end;
end;
private
myThread: TMyThread;
procedure TForm1.Button1Click(sender: TObject);
begin
myThread := TMyThread.Create(False);
end;
procedure TForm1.Button2Click(sender: TObject);
begin
if myThread <> nil then
begin
myThread.Terminate;
myThread.WaitFor;
FreeAndNil(myThread);
end;
end;