C++ Builder中自带了indy10控件,由于indy10的TCPClient接收方式是阻塞式的,所以需要一个线程来接收数据。
indy10本身有一个线程控件:
把它放在界面中就可以使用了。
我是在OnRun函数中添加自己的代码,虽然可以成功运行,但不知道是否规范。代码如下:
void __fastcall THeaderFooterForm::TCPClientRecThreadRun(TIdThreadComponent *Sender) { //判断是否建立连接 if(!TCPClient->Connected()) { return; } //判断InputBuffer是否为空 if(TCPClient->IOHandler->InputBufferIsEmpty()) { return; } len = TCPClient->IOHandler->InputBuffer->Size; //获取接收数据的长度 StrBuf = TCPClient->IOHandler->ReadString(len); //一次性读取len字节 MemoDisplay->Lines->Add(StrBuf); //显示接收到的数据 }
扩展资料:TIdThreadComponent组件介绍(摘自《Delphi7组件应用实例》P475)
TIdThreadComponent组件是TIdCustomThreadComponent子类,使用一个执行线程实现一个可使组件。
1.属性
(1)Active:指定组件内部线程是否正在运行。
(2)Priority:指定组件内部线程的调度优先级。
(3)StopMode:指定组件内部线程的Stoped属性值为True时系统的行为。
2.方法
(1)Create:创建并初始化一个TIdThreadComponent对象实例。
(2)Destroy:释放TIdThreadComponent对象实例。
(3)Start:启动或恢复组件的内部线程的执行。
(4)Stop:中断组件的内部线程的执行。
(5)Synchroize:在主应用程序线程中执行一个线程或程序方法,
(6)Terminate:请求终止组件内部线程的执行。
(7)TerminateAndWaitFor:组合Terminate和WaitFor方法,请求并等待组件内部线程的终止。
(8)WaitFor:等待直至线程执行完毕。
3.事件
(1)OnAfterExecute:线程执行完成时触发该事件。
(2)OnAfterRun:线程被中断,但仍可能再度恢复时触发该事件。
(3)OnBeforeExecute:线程将要进入内部控制循环时触发该事件。
(4)OnBeforeRun:线程将要在内部控制循环中执行迭代时触发该事件。
(5)OnCleanup:线程执行CleanUp方法时触发该事件。
(6)OnException:线程执行过程中出现异常时触发该事件。
(7)OnRun:线程开始执行时触发该事件。
(8)OnStoped:线程被停止时触发该事件。
(9)OnTerminate:线程终止时触发该事件。
另外附上一个自己写的Demo程序片段:
//Button1单击事件 procedure TForm1.Button1Click(Sender: TObject); begin //IdThreadComponent1.Active := true; //启动线程 IdThreadComponent1.Start; //和上一条语句一样的效果 end; //OnRun事件 procedure TForm1.IdThreadComponent1Run(Sender: TIdThreadComponent); begin inc(i); //i++ IdThreadComponent1.Synchronize(display); //使用Synchronize方法调用VCL控件,不然会卡顿甚至死机 //IdThreadComponent1.Active := false; //停止线程运行 IdThreadComponent1.Terminate; //结束线程,并进入OnTerminate事件,不然会反复执行线程 end; //显示函数 procedure TForm1.display(); begin Memo1.Lines.Add('display:' + IntToStr(i)); end;