线程里的代码如下
[code=Delphi(Pascal)]
unit FtpScan;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OleCtrls, SHDocVw, StdCtrls,MSHTML,Communal,Reverse,
IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdFTP,
ComCtrls,Unit1;const
MyMessage=WM_USER +1024;type
TFtpScan = class(TThread)
private
User:string;
Password:TStringList;
host:string;
mmo:TMemo;
protected
procedure Execute; override;
public
constructor Create(Users,hosts:string;Passwords:TStringList;TmpMemo:TMemo);
end;
var
CS:TRTLCriticalSection;//临界区implementationconstructor TFtpScan.Create(Users,hosts:string;Passwords:TStringList;TmpMemo:TMemo);
begin
host:=hosts;
User:=Users;
Password:=Passwords;
mmo:=TmpMemo;
InitializeCriticalSection(CS);
FreeOnTerminate := True; // 自动删除
inherited Create(False); // 直接运行
end;
//------------------------------------------------------------------------------
procedure TftpScan.Execute;
var
Idftp1:TIdFTP;
Passwords:TStringList;
i:Integer;
f:TextFile;
begin
Passwords:=TStringList.Create;
Idftp1:=TIdFTP.Create(nil); Idftp1.Host:=host;
Idftp1.Username:=User;
Idftp1.Port:=21; if Passwords.Count=0 then
begin
Passwords.Add('888');
Passwords.Add('123456');
Passwords.Add('654321');
Passwords.Add('123456789');
Passwords.Add(User);
Passwords.Add(User + '123');
Passwords.Add(User + '888');
Passwords.Add(User + '23456');
end; Passwords.Strings[4]:=User;
Passwords.Strings[5]:=User + '123';
Passwords.Strings[6]:=User + '888';
Passwords.Strings[7]:=User + '23456';
EnterCriticalSection(CS);//进入临界区
for i:= 0 to Passwords.Count -1 do
begin
Idftp1.Password:=Passwords.Strings[i];
try
IdFTP1.Connect(True,400); //设置连接时间
mmo.Lines.Add('主机:' + IdFTP1.Host + ' 用户名:' + IdFTP1.Username + ' 密码:' + IdFTP1.Password + ' 成功!');
IdFTP1.Disconnect; AssignFile(F,'ok.txt');
if FileExists('ok.txt') then
Append(f)
else
Rewrite(f);
Writeln(F,'主机:' + IdFTP1.Host + ' 用户名:' + IdFTP1.Username + ' 密码:' + IdFTP1.Password + ' 成功!');
CloseFile(f);
LeaveCriticalSection(CS);//退出临界区 Break;
except
mmo.Lines.Add('主机:' + IdFTP1.Host + ' 用户名:' + IdFTP1.Username + ' 密码:' + IdFTP1.Password + ' 失败!');
IdFTP1.Disconnect;
LeaveCriticalSection(CS);//退出临界区
end;
end;
DeleteCriticalSection(CS);
Passwords.Free; SendMessage(Form1.Handle,
MyMessage,
0,
0);end;
//------------------------------------------------------------------------------
每执行完一个线程后,向主窗体发送一个消息,主窗体计数器+1 当主窗体的计数器与所开的线程个数相等就说明所有线程执行完毕,现在的问题是,如果我开了56个线程,在某些机器上运行时,计数器只增加到55或者54(不设置临界区),总是有那么一两个线程被卡住,程序就不能进行下一步的操作,如果我设置了临界区的话,就如上面的代码,计数器只增加到28-35这个样子,是我的代码有问题,还是其它原因。有什么好的解决办法没?
[code=Delphi(Pascal)]
unit FtpScan;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OleCtrls, SHDocVw, StdCtrls,MSHTML,Communal,Reverse,
IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdFTP,
ComCtrls,Unit1;const
MyMessage=WM_USER +1024;type
TFtpScan = class(TThread)
private
User:string;
Password:TStringList;
host:string;
mmo:TMemo;
protected
procedure Execute; override;
public
constructor Create(Users,hosts:string;Passwords:TStringList;TmpMemo:TMemo);
end;
var
CS:TRTLCriticalSection;//临界区implementationconstructor TFtpScan.Create(Users,hosts:string;Passwords:TStringList;TmpMemo:TMemo);
begin
host:=hosts;
User:=Users;
Password:=Passwords;
mmo:=TmpMemo;
InitializeCriticalSection(CS);
FreeOnTerminate := True; // 自动删除
inherited Create(False); // 直接运行
end;
//------------------------------------------------------------------------------
procedure TftpScan.Execute;
var
Idftp1:TIdFTP;
Passwords:TStringList;
i:Integer;
f:TextFile;
begin
Passwords:=TStringList.Create;
Idftp1:=TIdFTP.Create(nil); Idftp1.Host:=host;
Idftp1.Username:=User;
Idftp1.Port:=21; if Passwords.Count=0 then
begin
Passwords.Add('888');
Passwords.Add('123456');
Passwords.Add('654321');
Passwords.Add('123456789');
Passwords.Add(User);
Passwords.Add(User + '123');
Passwords.Add(User + '888');
Passwords.Add(User + '23456');
end; Passwords.Strings[4]:=User;
Passwords.Strings[5]:=User + '123';
Passwords.Strings[6]:=User + '888';
Passwords.Strings[7]:=User + '23456';
EnterCriticalSection(CS);//进入临界区
for i:= 0 to Passwords.Count -1 do
begin
Idftp1.Password:=Passwords.Strings[i];
try
IdFTP1.Connect(True,400); //设置连接时间
mmo.Lines.Add('主机:' + IdFTP1.Host + ' 用户名:' + IdFTP1.Username + ' 密码:' + IdFTP1.Password + ' 成功!');
IdFTP1.Disconnect; AssignFile(F,'ok.txt');
if FileExists('ok.txt') then
Append(f)
else
Rewrite(f);
Writeln(F,'主机:' + IdFTP1.Host + ' 用户名:' + IdFTP1.Username + ' 密码:' + IdFTP1.Password + ' 成功!');
CloseFile(f);
LeaveCriticalSection(CS);//退出临界区 Break;
except
mmo.Lines.Add('主机:' + IdFTP1.Host + ' 用户名:' + IdFTP1.Username + ' 密码:' + IdFTP1.Password + ' 失败!');
IdFTP1.Disconnect;
LeaveCriticalSection(CS);//退出临界区
end;
end;
DeleteCriticalSection(CS);
Passwords.Free; SendMessage(Form1.Handle,
MyMessage,
0,
0);end;
//------------------------------------------------------------------------------
每执行完一个线程后,向主窗体发送一个消息,主窗体计数器+1 当主窗体的计数器与所开的线程个数相等就说明所有线程执行完毕,现在的问题是,如果我开了56个线程,在某些机器上运行时,计数器只增加到55或者54(不设置临界区),总是有那么一两个线程被卡住,程序就不能进行下一步的操作,如果我设置了临界区的话,就如上面的代码,计数器只增加到28-35这个样子,是我的代码有问题,还是其它原因。有什么好的解决办法没?
解决方案 »
- 如何获得外部程序SYSLISTVIEW32某行某列的图像索引?
- 从任务栏右键关闭程序引起的程序异常错误
- 请问如何在DBGrid中不同记录显示不同的颜色啊。我把我的源程序贴上来了,请高手帮忙!急!
- ADOQuery.SQL往ADOTable添加少量数据,如何使得数据敏感控件能实时更新且不影响应用程序效率?
- [dbnetlib]connectionopen(connect())sql sever 不存在或被拒绝。
- 怎样随窗体大小的变化缩放组件(急!!!!)
- 点击TButton关闭窗体时,怎样忽略其他控件的OnExit方法?
- 问个极简单的问题???
- 一个Client端调用接口的小问题
- 怎样在fastreport中打印窗体界面?
- 关于delphi中time的问题
- 把窗体的数据写到dbgrid的单元格
我建议你先把它暂时注释掉再试试!希望能成功!
unit Unit1;interfaceuses Windows, Classes;type
TMyThread = class(TThread)
private
procedure Execute; override;
end;implementationvar
CS: TRTLCriticalSection;{ TMyThread }procedure TMyThread.Execute;
begin
inherited;
EnterCriticalSection(CS); //进入临界区
/// <code>
/// 在这里写上你要实现的代码
/// </code>
LeaveCriticalSection(CS); //退出临界区
end;initialization
InitializeCriticalSection(CS);finalization
DeleteCriticalSection(CS);end.
我的代码是每个线程进来都会初始化一次,每个线程结束的时候都会删除一次,而且我也把DeleteCriticalSection(CS); 去掉了,还是老问题
你每次都初始化一次干嘛, 有的本来有线程已经在临界区里, 有的又去初始化他..,然后以退出,不乱套了应该在那个单元初始化的地方,
initialization
初始化临界区
finalization
procedure TftpScan.Execute;
begin
try
// 其他代码放这里边
finally
// 输出异常信息
输出SysErrorMessage(GetLastError)
SendMessage(Form1.Handle,
MyMessage,
0,
0);
end;
end;
你也看到我的代码了,如果把TftpScan.Execute里面的代码全部放进临界区里的话,我每个线程要执行的关键代码就成了保护数据,这样会降低程序效率的,有什么好办法没,
别担心分的问题,我出手很大方的。
另外离开临界区的时候
EnterCriticalSection
try
// 代码
finally
LeaveCriticalSection
end;确保每次都有退出
mmo.Lines.Add('主机:' + IdFTP1.Host + ' 用户名:' + IdFTP1.Username + ' 密码:' + IdFTP1.Password + ' 成功!');
LeaveCriticalSection(CS); //退出临界区
EnterCriticalSection(CS); //进入临界区
mmo.Lines.Add('主机:' + IdFTP1.Host + ' 用户名:' + IdFTP1.Username + ' 密码:' + IdFTP1.Password + ' 失败!');
LeaveCriticalSection(CS); //退出临界区退出是保证有的,我的意思是如何做能把受到保护的数据缩到最小,把程序的效率影响到最小。我如上的代码可以做到吗?
其他好象必须放进来
另外操作VCL可以挪出来, 用发消息方式代替, 要写的数据放到结构体中,参数是结构体,放到主线程去处理,
要保护的地方好象只有写文件那块
for i:= 0 to Passwords.Count -1 do
begin
EnterCriticalSection(CS);
.
.
.
LeaveCriticalSection(CS);
end;
同时也感谢其他朋友
同时也感谢其他朋友