线程里的代码如下
[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这个样子,是我的代码有问题,还是其它原因。有什么好的解决办法没?

解决方案 »

  1.   

    我觉得是DeleteCriticalSection(CS)导致的; 当你一个线程执行到DeleteCriticalSection(CS); 别的线程都还在执行 ,你删除可能会有问题
    我建议你先把它暂时注释掉再试试!希望能成功!
      

  2.   


    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.
      

  3.   

    PostThreadMessage會更保險一點....
      

  4.   


    我的代码是每个线程进来都会初始化一次,每个线程结束的时候都会删除一次,而且我也把DeleteCriticalSection(CS); 去掉了,还是老问题
      

  5.   

    你那临界区不是这么用的
    你每次都初始化一次干嘛, 有的本来有线程已经在临界区里, 有的又去初始化他..,然后以退出,不乱套了应该在那个单元初始化的地方,
    initialization
    初始化临界区
    finalization
      

  6.   

    测下看那边统计的对不对, 如果对的话,就是中间代码有异常退出了
    procedure TftpScan.Execute;
    begin
      try
      // 其他代码放这里边
      finally
         // 输出异常信息
          输出SysErrorMessage(GetLastError)
         SendMessage(Form1.Handle,
                     MyMessage,
                     0,
                     0);
      end;
    end;
      

  7.   

    这个我懂了,就是说,在第一个线程开始的时候创建的临界区(单元被使用),最后一个线程结束的时候删除临界区(单元被释放)。
    你也看到我的代码了,如果把TftpScan.Execute里面的代码全部放进临界区里的话,我每个线程要执行的关键代码就成了保护数据,这样会降低程序效率的,有什么好办法没,
    别担心分的问题,我出手很大方的。
      

  8.   

    基本就把你要同步的代码放进去
    另外离开临界区的时候 
    EnterCriticalSection
    try
     // 代码
    finally
      LeaveCriticalSection
    end;确保每次都有退出
      

  9.   

          EnterCriticalSection(CS);        //进入临界区
          mmo.Lines.Add('主机:' + IdFTP1.Host + ' 用户名:' + IdFTP1.Username + ' 密码:' + IdFTP1.Password + ' 成功!');
          LeaveCriticalSection(CS);        //退出临界区
          EnterCriticalSection(CS);         //进入临界区
          mmo.Lines.Add('主机:' + IdFTP1.Host + ' 用户名:' + IdFTP1.Username + ' 密码:' + IdFTP1.Password + ' 失败!');
          LeaveCriticalSection(CS);        //退出临界区退出是保证有的,我的意思是如何做能把受到保护的数据缩到最小,把程序的效率影响到最小。我如上的代码可以做到吗?
      

  10.   

    那个FTP 你是单独建在线程中的, 不需要保护的, 可以挪出去, 但是要加try 
    其他好象必须放进来
    另外操作VCL可以挪出来, 用发消息方式代替,  要写的数据放到结构体中,参数是结构体,放到主线程去处理,
    要保护的地方好象只有写文件那块
      

  11.   

     
    for i:= 0 to Passwords.Count -1 do
    begin
    EnterCriticalSection(CS); 
    .
    .
    .
    LeaveCriticalSection(CS); 
    end;
      

  12.   

    http://topic.csdn.net/u/20100512/14/5e7d0e70-a19b-4b80-a9cc-922b9999b927.html结贴,新贴,sanguomi,wellnj进来接分
    同时也感谢其他朋友
      

  13.   

    http://topic.csdn.net/u/20100512/14/5e7d0e70-a19b-4b80-a9cc-922b9999b927.html结贴,新贴,sanguomi,wellnj进来接分
    同时也感谢其他朋友