线程使用的问题,贴上代码,求高手指正.(嫌分少,可RMB求例程) ( 积分: 21 )

  • 主题发起人 主题发起人 su820127
  • 开始时间 开始时间
S

su820127

Unregistered / Unconfirmed
GUEST, unregistred user!
此问题在多个论坛发问多次,没什么人顶..积分不多,,现在大富翁环境不景,实在不想再伸请垃圾号拿积分,,愿以RMB求一清晰学习例程.
我用了两个TTHREAD后,显视可以连接上,但就收不到信息,好像有一线程死掉了,,
贴上代码,高手们帮忙指正一下错在哪里.
program Client;

{$APPTYPE CONSOLE}
uses
SysUtils,Windows,shellapi,Classes,IdTCPClient;
{----------------二个线程类---------------------}
type
TClientThreadone = class(TThread)
private
protected
procedure Execute;
override;
Public
constructor Create;
destructor Destroy;
override;
end;

TClientThreadtwo = class(TThread)
IdTCPClient :TidTcpClient;
private
protected
procedure Execute;
override;
Public
constructor Create;
destructor Destroy;
override;
end;

{----------------全局变量--------------------}
var
ClientThreadOne: TClientThreadone;
ClientThreadtwo: TClientThreadtwo;
IdTCPClient1 :TIdTCPClient;
{----------------连接-------------------}
function GotoServer(BThread: TIdTCPClient):Boolean;
begin

try
if BThread.Connected then

BThread.Disconnect;
BThread.Host:= '127.0.0.1 ';
BThread.Port:=8201;
BThread.Connect;
Result:=True;
except
Result:=False;
end;

end;

{----------------发送数据-----------------------}
procedure SendToClient(AThread: TIdTCPClient;Cmd:String);
begin

Try
if not AThread.Connected then
exit;
AThread.IOHandler.WriteLn(Cmd);
Except
AThread.Disconnect;
end;

end;

{----------------创建线程-----------------------}
constructor TClientThreadone.Create;
begin

inherited Create(True);
FreeOnTerminate:=True;
end;

constructor TClientThreadtwo.Create;
begin

inherited Create(True);
FreeOnTerminate:=True;
IdTCPClient :=TIdTCPClient.Create(nil);
while not IdTCPClient.Connected do

begin

if gotoserver(IdTCPClient) then

SendToClient(IdTCPClient, 'comeon ');
end;

end;

destructor TClientThreadtwo.Destroy;
begin

writeln( '线程二:连接断开 ');
IdTCPClient.Free;
inherited destroy;
end;

{----------------线程二监听消息--------------------}
procedure TClientThreadtwo.Execute;
var
Str:String;
begin

while not Terminateddo

begin

try
str:=IdTCPClient.IOHandler.ReadLn();
writeln( '线程二收到消息: '+ str);
except
ClientThreadTwo.Destroy;
end;

end;

end;

{----------------线程一监听消息---------------------}
procedure TClientThreadone.Execute;
var
Str:String;
begin

while not Terminateddo

begin

try
Str:=IdTCPClient1.IOHandler.ReadLn();
writeln( '线程一收到消息: '+ str);
except
ClientThreadOne.Destroy;
end;

end;

end;

procedure MainConnect;
begin

IdTCPClient1 :=TIdTCPClient.Create(nil);
try
while not IdTCPClient1.Connecteddo

begin

if GotoServer(IdTCPClient1) then

begin

if not IdTCPClient1.Connected then
exit;
SendToClient(IdTCPClient1, 'comeon ');
ClientThreadOne:=TClientThreadone.Create;
//创建他们
ClientThreadtwo :=TClientThreadtwo.Create ;
end;

sleep(5500);
end;

ClientThreadOne.Execute;
ClientThreadTwo.Execute;
except
IdTCPClient1.Free ;
exit;
end;

end;

destructor TClientThreadone.Destroy;
begin

MainConnect;
inherited destroy;
end;

begin

MainConnect;
end.

单独用一线程就正常,但运行两个线程后两个Execute都不工作,这是怎么回事阿?
 
多线程使用公共资源要用临界区保护公共资源。
就是一个线程在使用的时候,另一个线程处于等候状态,等到一个线程使用完毕,下一个线程才能使用(当然,这是在对公共资源有变更的时候才使用)。
还有你的MainConnect明显有问题,线程创建之后自动会自行Execute过程,不用你手动取执行他。
我绝得你这完全没有必要定义两个线程类,代码都一样的,可以整合成一个线程定义啊。为什么要创建两次?
线程二如果要单独使用一个TcpClient的话应该内部定义,内部创建,为什么要用公共变量?这样很容易到最后自己都搞不清哪个线程用的是哪个TcpClient。
 
如果我两个线程都要进入死循环工作,哪该怎么办?
定义两个类的思路,应该没什么问题吧?
其实我只是希望一个Client能够接收文件,,而别一个client能正常聊天,互不影响而已,这也这么大难度么..
以上的代码我知道是有错误,只是不知该换哪种方法去解决
上面的代码测试中,当线程二创建后,线程一的client的连接好像就死掉了,free掉线程二后,线程一的client会重新连接过,,不知道是不是在线程二的死循环阻塞下死掉了,这个不懂
 
program Client;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows, Classes, IdTCPClient;
type
TClientThread = class(TThread)
Private
IdTCPClient : TidTcpClient;
FFirstCmd : string;
FThreadName : string;
Protected
procedure Execute;
Override;
Public
constructor Create(FirstCmd : string;
ThreadName : string);
destructor Destroy;
Override;
end;
{----------------全局变量--------------------}
var
ClientThreadOne : TClientThread;
ClientThreadtwo : TClientThread;
{----------------连接-------------------}
function GotoServer(ATcpClient : TidTcpClient) : Boolean;
begin
try
if ATcpClient.Connected then
ATcpClient.Disconnect;
ATcpClient.Host := '127.0.0.1 ';
ATcpClient.Port := 8201;
ATcpClient.Connect;
Result := True;
except
Result := False;
end;
end;
{----------------发送数据-----------------------}
procedure SendToClient(ATcpClient : TidTcpClient;
Cmd : string);
begin
if not ATcpClient.Connected then
exit;
ATcpClient.IOHandler.WriteLn(Cmd);
end;
{----------------创建线程-----------------------}
constructor TClientThread.Create(FirstCmd : string;
ThreadName : string);
begin
inherited Create(False);
FreeOnTerminate := True;
IdTCPClient := TidTcpClient.Create(nil);
if not GotoServer(IdTCPClient) then
Self.Terminate;
end;

destructor TClientThread.Destroy;
begin
WriteLn(FThreadName + ':连接断开 ');
try
IdTCPClient.Disconnect;
except
end;
IdTCPClient.Free;
inherited Destroy;
end;

{----------------线程监听消息--------------------}
procedure TClientThread.Execute;
var
Str : string;
begin
if FFirstCmd <> '' then
SendToClient(IdTCPClient, 'comeon ');
while not Terminateddo
begin
Str := IdTCPClient.IOHandler.ReadLn();
WriteLn(FThreadName + '收到消息: ' + Str);
end;
end;

procedure MainConnect;
begin
ClientThreadOne := TClientThread.Create('comeon ', '线程一');
//创建他们
ClientThreadtwo := TClientThread.Create('comeon ', '线程二');
end;

begin
MainConnect;
end.
给你的程序改了一下,你试试看,我没有调试过。
 
procedure TClientThread.Execute;
var
Str : string;
begin
if FFirstCmd <> '' then
//SendToClient(IdTCPClient, 'comeon ');
上面没写对
SendToClient(IdTCPClient, FFirstCmd);
while not Terminateddo
begin
Str := IdTCPClient.IOHandler.ReadLn();
WriteLn(FThreadName + '收到消息: ' + Str);
end;
end;
哦,上面的有一点问题,还有就是你这个程序没有结束的事件,所以线程死循环。最好写一个程序终止的时候终止线程的事件。
 
1.
inherited Create(True);
FreeOnTerminate := True;
。。。。其它初始化代码
这时线程并没有启动动。创建实例之后,调用Resume才能启动。
否则就传False进去,如下:
inherited Create(False);
FreeOnTerminate := True;
2.不要直接调用线程的Execute.创建线程之后,线程参数为True,则表示暂时不执行线程。False为立即启动线程。你再看看吧。可能是你对线程不是很理解吧。
 
刚学习多线程的..
inherited Create(true);//再用Execute调用后,可保持着连接.
inherited Create(false);//或用Resume调用,则上面的程序一闪而过就没有了,好像不能进入到Execute的工作中...请问这是为什么?
 
在任务管理器里监视一下程序有几个线程。
 
后退
顶部