主界面建立线程,用TIdTCPClient读取 服务器端发来的数据
procedure TForm3.Button1Click(Sender: TObject);
begin
recvthread := TRev1.Create(True);
recvthread.FreeOnTerminate := True;
recvthread.Resume;
end;线程单元中:procedure TRev1.Execute;
begin
{ Place thread code here }
while not Terminated do
begin
Form3.Memo1.Lines.Add(Form3.IdTCPClient1.ReadLn('EOF', -1 , -1)); //关闭时被卡这里,无法正常关闭线程!!你说咋办??????
end;
end;问题是,我在界面关闭线程时,
procedure TForm3.Button3Click(Sender: TObject);
begin
recvthread.Terminate;////////////////////线程无法关闭,,, 直接关闭窗口将引发异常!!! 我用delphi5
end;
请问各位同志,有什么解决方法吗??
procedure TForm3.Button1Click(Sender: TObject);
begin
recvthread := TRev1.Create(True);
recvthread.FreeOnTerminate := True;
recvthread.Resume;
end;线程单元中:procedure TRev1.Execute;
begin
{ Place thread code here }
while not Terminated do
begin
Form3.Memo1.Lines.Add(Form3.IdTCPClient1.ReadLn('EOF', -1 , -1)); //关闭时被卡这里,无法正常关闭线程!!你说咋办??????
end;
end;问题是,我在界面关闭线程时,
procedure TForm3.Button3Click(Sender: TObject);
begin
recvthread.Terminate;////////////////////线程无法关闭,,, 直接关闭窗口将引发异常!!! 我用delphi5
end;
请问各位同志,有什么解决方法吗??
Form3.Memo1.Lines.Add(Form3.IdTCPClient1.ReadLn('EOF', -1 , -1)); //关闭时被卡这里,无法这句有点问题,在后面加这个看看如何:
sleep(500);
recvthread.Terminate;
修改为:
recvthread.Terminated := true;同样,要和上面的修改配合
procedure TForm3.Button1Click(Sender: TObject);
begin
recvthread := TRev1.Create(memo1,IdTCPClient1);//传入参数,在线程中更新memo
end;在线程单元中,如下:unit Unit4;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
ComCtrls;
type
TRev1 = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
procedure Write_memo;
public
constructor Create(memo:Tmemo;IdTCPClient:TIdTCPClient);
end;implementation
uses unit3;
{ Important: Methods and properties of objects in VCL can only be used in a
method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure TRev.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }{ TRev }
constructor TRev1.Create(memo:Tmemo;IdTCPClient:TIdTCPClient);
begin
memo.Lines.Clear;
FreeonTerminate:=true;
inherited Create(false);
end;
procedure TRev1.Execute;
begin
{ Place thread code here }
while not Terminated do
begin
// Form3.Memo1.Lines.Add(Form3.IdTCPClient1.ReadLn('EOF', -1 , -1));
synchronize(Write_memo);
end;
end;procedure TRev1.Write_memo;
begin
memo.lines.add(IdTCPClient.ReadLn('EOF', -1 , -1));
end;end.还是编译不成功!!提示procedure TRev1.Write_memo 中用到的参数memo没定义 ,,这个memo就是来自界面单元的。。
线程当然得不到结束.
1,为什么不在主线程用INDYTCPCLIENT?INDY控件组设计的一个特点就是为主线程运行阻塞方式客户端防界面冻结作了一定处理.2,接收数据为什么不设置超时?
3,用线程,尽可能不要直接去访问FORM这些GDI显示的.尽管有Synchronize可以来保证线程
安全,但它实际是用消息机制切换任务到主线程执行,失去了线程的意义.
通过 // 一定时间检查是否有数据可读
IOHandler.CheckForDataOnSource(GetTimeout);
Result := IOHandler.InputBuffer.Size;
if Result > 0 then // 有数据到达再用相应的
IOHandler.ReadXXXX 读出数据。循环该过程,并且判断线程是否结束。严重支持楼上仁兄建议的,在线程里 PostMessage 给主线程,
让主线程操作VCL
"还是编译不成功!!提示procedure TRev1.Write_memo 中用到的参数memo没定义 ,,这个memo就是来自界面单元的。。"在线程中定义一个TMemo类型的变量memo1,在constructor TRev1.Create(memo:Tmemo;IdTCPClient:TIdTCPClient);中初始化memo1,并把memo赋值给memo1
例如:
constructor TRev1.Create(var memo:Tmemo;IdTCPClient:TIdTCPClient);
begin
memo1:=Tmemo.Create(nil);
memo1 := memo;
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
recvthread := TRev1.Create(memo1,IdTCPClient1);//传入参数,在线程中更新memo
end;在线程单元中,如下:unit Unit4;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
ComCtrls;
type
TRev1 = class(TThread)
private
Mymemo:Tmemo;
IdTCPClient1:TIdTCPClient;
{ Private declarations }
protected
procedure Execute; override;
procedure Write_memo;
public
constructor Create(memo:Tmemo;IdTCPClient:TIdTCPClient);
end;implementation
uses unit3;
{ Important: Methods and properties of objects in VCL can only be used in a
method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure TRev.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }{ TRev }
constructor TRev1.Create(memo:Tmemo;IdTCPClient:TIdTCPClient);
begin
inherited Create(false);
//memo.Lines.Clear;
Mymemo := memo;
IdTCPClient1:= IdTCPClient;
FreeonTerminate:=true;
end;
procedure TRev1.Execute;
begin
Mymemo.Lines.Clear;
{ Place thread code here }
while not Terminated do
begin
// Form3.Memo1.Lines.Add(Form3.IdTCPClient1.ReadLn('EOF', -1 , -1));
synchronize(Write_memo);
end;
end;procedure TRev1.Write_memo;
begin
Mymemo.lines.add(IdTCPClient1.ReadLn('EOF', -1 , -1));
end;end.
我用的 indy 是10.1.5:unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
StdCtrls;
const
WM_GETINFO = WM_USER + 110;
type
TReceiver = class(TThread) protected
procedure Execute; override;
public
Connection: TidTCPConnection;
MsgHandle: THandle;
end; TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
IdTCPClient1: TIdTCPClient;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
/// 界面上需要处理线程Post 出来的 Message
procedure WMGetInfo(var msg: TMessage); message WM_GETINFO;
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
with TReceiver.Create(true) do
begin
FreeOnTerminate := true;
Connection := self.IdTCPClient1;
MsgHandle := Handle;
resume;
end;
end;procedure TForm1.WMGetInfo(var msg: TMessage);
var
buf: PChar;
iLen: integer;
strTmp: string;
begin iLen := msg.WParam;
buf := PChar(msg.LParam);
SetLength(strTmp, iLen);
Move(buf^, strTmp[1], iLen);
//// 线程抛出的信息被放到 strtmp 中,
//// 下面可以加入你自己的处理
Memo1.Lines.Add(strTmp);
/// 记得 Free,不然存在内存泄漏。
Freemem(buf);
end;
{ TReceiver }procedure TReceiver.Execute;
var
buf: PChar;
iLen: integer;
strTmp: string;
iRec: integer;
begin
while not Terminated do
begin
/// 10 ms 检查一次是否有数据到达
Connection.IOHandler.CheckForDataOnSource(10);
iRec := Connection.IOHandler.InputBuffer.Size;
if iRec > 0 then
begin
/// 你的接收数据处理过程
strTmp := Connection.IOHandler.ReadString(iRec); GetMem(buf, iRec);
Move(strTmp[1], buf^, iRec);
/// 需要向主界面输出信息时,向主界面的窗口句柄
/// Postmessage , SendMessage 也行。
PostMessage(MsgHandle, WM_GETINFO, iRec, integer(buf));
end;
end;
end;end.
Connection.IOHandler.CheckForDataOnSource(10);//CheckForDataOnSource(10);找不到该方法
iRec := Connection.IOHandler.InputBuffer.Size;//InputBuffer.Size也找不着该属性
我用的是10.1.5
我已经说过很多次了。