多线程问题哪里没有同步好?

Mit1208 2010-09-03 09:51:29
程序在检测的时候,有时关闭会出现Read错误,但有时也不出现.不知道哪里的同步问题错误了.

但是...如果不关闭程序.它也能检测完~~~



线程部分:

unit DetectProxy;

interface

uses
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;

implementation

uses 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;
...全文
82 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Mit1208 2010-09-04
  • 打赏
  • 举报
回复
按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;


Mit1208 2010-09-04
  • 打赏
  • 举报
回复
在线程里不是使用synchronize(ReturnMessage)了吗?
把ProxyIndex :=ProxyIndex + 1;放在ReturnMessage也算是同步了吧?
sanguomi 2010-09-04
  • 打赏
  • 举报
回复
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;

Hexpate 2010-09-04
  • 打赏
  • 举报
回复
既然来领分, 那也得把方案写下来:
destructor TDetectProxy.Destroy;
begin
FreeAndNil(idhttp1);
inherited Destroy;
end;

改为

destructor TDetectProxy.Destroy;
begin
Waitfor;
FreeAndNil(idhttp1);
inherited Destroy;
end;
iqyely 2010-09-03
  • 打赏
  • 举报
回复
来学习下
sanguomi 2010-09-03
  • 打赏
  • 举报
回复
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; 同步

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧