程序在检测的时候,有时关闭会出现Read错误,但有时也不出现.不知道哪里的同步问题错误了.但是...如果不关闭程序.它也能检测完~~~线程部分:unit DetectProxy;interfaceuses
  SysUtils,Windows,Classes,IdHTTP,ComCtrls,Controls;type
  TDetectProxy = class(TThread)
  private
    { Private declarations }
    Idhttp1:TIdHTTP;        //IDHTTP
    ProxyStat:string;      //代理状态
  protected
    procedure Execute; override;
    procedure ReturnMessage;
    procedure GetProxy(out ip: string;out Pt:integer);
    function DetectIP(ServerIP: string; ServerPort: Integer):Boolean;
  public
    constructor Create;
    destructor Destroy;override;
  end;implementationuses Unit1;var
  AccountIndex:Integer = -1;
  ProxyIndex:Integer = -1;{ TDetectProxy }constructor TDetectProxy.Create;
begin
  inherited Create(False);
  Idhttp1:=TIdHTTP.Create(nil);
end;destructor TDetectProxy.Destroy;
begin
  FreeAndNil(idhttp1);
  inherited Destroy;
end;//获取代理
procedure TDetectProxy.GetProxy(out ip: string;out Pt:integer);
var
  s: string;
begin
    if ProxyIndex > ProxyList.Count -1 then Exit;
    s := ProxyList[ProxyIndex];
    ip:= ExtractString(s, ':', 0);
    Pt := StrToInt(ExtractString(s, ':', 1));
end;
//检测代理------不知道为何.使用这个函数,竟然检测出来的结果不正确!
function TDetectProxy.DetectIP(ServerIP: string; ServerPort: Integer):Boolean;
const
  DetectStr='手机号码';
  DetectUrl='http://www.hao123.com/haoserver/showjicc.htm';
var
  DetectResult:string;
begin
  with Idhttp1.ProxyParams do
  begin
    ProxyServer :=ServerIP ;
    ProxyPort :=ServerPort ;
  end;
  Idhttp1.Response.CharSet :='GB2312';
  try
    DetectResult :=Idhttp1.Get(DetectUrl);
  finally
    Result :=Pos(DetectStr,DetectResult) <> 0;
  end;
end;//将数据写入到ListView
procedure TDetectProxy.ReturnMessage;
begin
    with Form1.ListView3.Items.Add do
    begin
      Caption :=ProxyStat;
      SubItems.Add(LoginStat);
      SubItems.Add(CommentStat);
      SubItems.Add(VoteStat);
    end;
    ProxyIndex :=ProxyIndex + 1;
end;procedure TDetectProxy.Execute;
const
  DetectStr='手机号码';
  DetectUrl='http://www.hao123.com/haoserver/showjicc.htm';
var
  OpenResult:string;
  Proxy:string;
  Port:Integer;
begin
  EnterCriticalSection(Critical);
  try
    ProxyIndex :=ProxyIndex +1;
  finally
    LeaveCriticalSection(Critical);
  end;
  while not Terminated do
  begin
    GetProxy(Proxy,Port);
    with Idhttp1.ProxyParams do              //-----------检测代理--------------
    begin
      ProxyServer :=Proxy;
      ProxyPort :=Port;                      //将检测代理的部分写在这里
    end;
    idhttp1.Response.CharSet :='GB2312';
    try                                      //可以正常检测
      OpenResult :=Idhttp1.Get(DetectUrl);
    except
    end;                                    //------------结束检测--------------
    if Pos(DetectStr,OpenResult) > 0 then
    begin
      ProxyStat :=Proxy + '可用';
    end
    else
    begin
      ProxyStat :=Proxy + '不可用';
    end;
    Synchronize(ReturnMessage);
    if (ProxyIndex >ProxyList.Count -1 ) then Break;
  end;
end;调用单元文件://全局变量
var 
  ThreadList:TList; 
  ProxyList:TStringList;
  Critical:TRTLCriticalSection;
  StartThread:array[0..9] of TDetectProxy;
//提取字符串函数
function ExtractString(const Source: string; const Delemiter: Char; Index: Integer):string;
var
  sourceList:TStringList;
begin
  sourceList :=TStringList.Create;
  try
    sourceList.Delimiter :=Delemiter;
    sourceList.DelimitedText :=Source;
    Result :=sourceList[Index];
  finally
    sourceList.Free;
  end;
end;
//窗体创建时初始化数据
procedure TForm1.FormCreate(Sender: TObject);
begin
  ThreadList :=TList.Create;
  ProxyList :=TStringList.Create;
  InitializeCriticalSection(Critical);
end;//窗体销毁时删除创建的数据
procedure TForm1.FormDestroy(Sender: TObject);
var
  i:Integer;
begin
  for i := 0 to ThreadList.Count -1 do
  begin
    TThread(ThreadList[i]).Terminate;
    TThread(ThreadList[i]).Free;
  end;
  ThreadList.Free;
  ProxyList.Free;
  DeleteCriticalSection(Critical);
end;
//导入代理
procedure TForm1.LoadProxyClick(Sender: TObject);
var
  i:Integer;
  Proxy,Port:string;
  IPList:TStringList;
begin
  IPList :=TStringList.Create;
  OpenDialog1.FileName :='Proxy.txt';
  if OpenDialog1.Execute then
    IPList.LoadFromFile(OpenDialog1.FileName);
  ProxyList.Assign(IPList);
  try
    if Pos(':',IPList.Text) = 0 then Exit;
    for I := 0 to IPList.Count - 1 do
    begin
      Proxy :=ExtractString(IPList[i],':',0);
      Port :=ExtractString(IPList[i],':',1);
      with ListView2.Items.Add do
      begin
        Caption :=Proxy ;
        SubItems.Add(Port);
      end;
    end;
  finally
    IPList.Free;
  end;
end;
//调用线程
procedure TForm1.StartClick(Sender: TObject);
var
  i:Integer;
begin
  for i := Low(StartThread) to High(StartThread) do
  begin
    StartThread[i]:=TDetectProxy.Create;
    ThreadList.Add(StartThread[i]);
  end;
end;

解决方案 »

  1.   

    procedure TDetectProxy.ReturnMessage;
    begin
        with Form1.ListView3.Items.Add do
        begin
          Caption :=ProxyStat;
          SubItems.Add(LoginStat);
          SubItems.Add(CommentStat);
          SubItems.Add(VoteStat);
        end;
        ProxyIndex :=ProxyIndex + 1;  ProxyIndex :=ProxyIndex + 1; 同步
      

  2.   

    在线程里不是使用synchronize(ReturnMessage)了吗?
    把ProxyIndex :=ProxyIndex + 1;放在ReturnMessage也算是同步了吧?
      

  3.   

    按1楼朋友所说,改为了下边代码,可还是出现Read错误~procedure TDetectProxy.ReturnMessage;
    begin
        with Form1.ListView3.Items.Add do
        begin
          Caption :=ProxyStat;
          SubItems.Add(LoginStat);
          SubItems.Add(CommentStat);
          SubItems.Add(VoteStat);
        end;
    end;procedure TDetectProxy.Execute;
    const
      DetectStr='手机号码';
      DetectUrl='http://www.hao123.com/haoserver/showjicc.htm';
    var
      OpenResult:string;
      Proxy:string;
      Port:Integer;
    begin
      while not Terminated do
      begin
        EnterCriticalSection(Critical);
        try
          ProxyIndex :=ProxyIndex +1;
        finally
          LeaveCriticalSection(Critical);
        end;
        GetProxy(Proxy,Port);
        with Idhttp1.ProxyParams do              //-----------检测代理--------------
        begin
          ProxyServer :=Proxy;
          ProxyPort :=Port;                      //将检测代理的部分写在这里
        end;
        idhttp1.Response.CharSet :='GB2312';
        try                                      //可以正常检测
          OpenResult :=Idhttp1.Get(DetectUrl);
        except
        end;                                    //------------结束检测--------------
        if Pos(DetectStr,OpenResult) > 0 then
        begin
          ProxyStat :=Proxy + '可用';
          LoginStat :='登陆成功';
          CommentStat :='评论成功';
          VoteStat :='投票成功';
        end
        else
        begin
          ProxyStat :=Proxy + '不可用';
          LoginStat :='登陆失败';
          CommentStat :='评论失败';
          VoteStat :='投票失败';
        end;
        Synchronize(ReturnMessage);
        if (ProxyIndex >ProxyList.Count -1 ) then Break;
      end;
    end;
      

  4.   

    既然来领分, 那也得把方案写下来:
    destructor TDetectProxy.Destroy;
    begin
      FreeAndNil(idhttp1);
      inherited Destroy;
    end;改为destructor TDetectProxy.Destroy;
    begin
      Waitfor;
      FreeAndNil(idhttp1);
      inherited Destroy;
    end;
      

  5.   

    destructor TDetectProxy.Destroy;
    begin
      Waitfor;
      FreeAndNil(idhttp1);
      inherited Destroy;
    end;这样的代码肯定有问题
    在线程里 调用 Waitfor,肯定会把自身挂起, 造成线程死锁,
     FreeAndNil(idhttp1);
      inherited Destroy;
    这俩句是没法执行下去的另外最好是开一个线程管理线程创建和释放,这样不会影响主线程
    线程管理 执行创建和释放功能,释放时在 Terminate 后加 waitfor, 等待那线程执行完,再释放下一个
     for i := 0 to ThreadList.Count -1 do
      begin
        TThread(ThreadList[i]).Terminate;
        TThread(ThreadList[i]).waitfor;
      end;