关于多线程下子线程使用父线程资源的问题。 ( 积分: 50 )

  • 主题发起人 主题发起人 piaosiy
  • 开始时间 开始时间
P

piaosiy

Unregistered / Unconfirmed
GUEST, unregistred user!
多线程下子线程要怎么样才能使用父线程资源?代码如下:
unit ufrmPing;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls,ShellApi, StdCtrls, IdBaseComponent, IdComponent,
IdRawBase, IdRawClient, IdIcmpClient,IniFiles;
type
TfrmPing = class(TForm)
Memo1: TMemo;
Timer2: TTimer;
procedure Timer2Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

procedure ICMPping1(Ptr:Pointer);stdcall;
var
frmPing: TfrmPing;
IPadr1,SFileName:string;
IP1IsReturn:boolean;
IdIcmpClient1: TIdIcmpClient;
implementation
{$R *.dfm}
procedure ICMPping1(Ptr:Pointer);stdcall;
begin
if IP1IsReturn=False then
frmPing.Memo1.Lines.Add('Request timed out.');
//主要是上面这句。编译后运行会出现 "0x0045ecc3"指令引用的"0x000002f8"内存。该内存不能为"read"
的错误。
IdIcmpClient1.Host:=IPadr1;
//IdIcmpClient1为Form Create 的时候动态定义的,IPadr1 为欲发送ICMP包的IP地址
IdIcmpClient1.ReceiveTimeout:=2000;
IdIcmpClient1.Ping();
IP1IsReturn:=False;
//如有正确返回ICMP包(即能Ping通)此变量将置True.
end;

procedure TfrmPing.Timer2Timer(Sender: TObject);
//Form Create 时触发该定时器,间隔10秒触发一次。
var
IPping1:Thandle;
ThreadID1:DWORD;
begin
if Trim(IPadr1)<>'' then
begin
IPping1:= CreateThread(nil,0,@ICMPping1,nil,0,ThreadID1);
end;
end;
end.
整个程序是想实现一个类似于Ping命令的功能,这里仅给出了Ping 不通时出问题的关键部分,请问应如何修改才能解决该内存不能为&quot;read&quot;
的问题?
 
多线程下子线程要怎么样才能使用父线程资源?代码如下:
unit ufrmPing;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls,ShellApi, StdCtrls, IdBaseComponent, IdComponent,
IdRawBase, IdRawClient, IdIcmpClient,IniFiles;
type
TfrmPing = class(TForm)
Memo1: TMemo;
Timer2: TTimer;
procedure Timer2Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

procedure ICMPping1(Ptr:Pointer);stdcall;
var
frmPing: TfrmPing;
IPadr1,SFileName:string;
IP1IsReturn:boolean;
IdIcmpClient1: TIdIcmpClient;
implementation
{$R *.dfm}
procedure ICMPping1(Ptr:Pointer);stdcall;
begin
if IP1IsReturn=False then
frmPing.Memo1.Lines.Add('Request timed out.');
//主要是上面这句。编译后运行会出现 &quot;0x0045ecc3&quot;指令引用的&quot;0x000002f8&quot;内存。该内存不能为&quot;read&quot;
的错误。
IdIcmpClient1.Host:=IPadr1;
//IdIcmpClient1为Form Create 的时候动态定义的,IPadr1 为欲发送ICMP包的IP地址
IdIcmpClient1.ReceiveTimeout:=2000;
IdIcmpClient1.Ping();
IP1IsReturn:=False;
//如有正确返回ICMP包(即能Ping通)此变量将置True.
end;

procedure TfrmPing.Timer2Timer(Sender: TObject);
//Form Create 时触发该定时器,间隔10秒触发一次。
var
IPping1:Thandle;
ThreadID1:DWORD;
begin
if Trim(IPadr1)<>'' then
begin
IPping1:= CreateThread(nil,0,@ICMPping1,nil,0,ThreadID1);
end;
end;
end.
整个程序是想实现一个类似于Ping命令的功能,这里仅给出了Ping 不通时出问题的关键部分,请问应如何修改才能解决该内存不能为&quot;read&quot;
的问题?
 
使用Tthread类,类中访问VCL要同步
 
不用Tthread类直接CreateThread不行吗?能否为我解释一下为什么会出现这个错误?是由什么原因引起的?
 
如果不幸遇到如下执行步骤就会产生异常(这还只是无数中可能性中的一种):
主线程屏幕刷新->读取frmPing.Memo1.Lines(假设读到地址2f8)->系统线程切换->子线程执行frmPing.Memo1.Lines.Add->frmPing.Memo1内部Lines重新分配内存, frmPing.Memo1.Lines现在指向新内存地址, 原内存地址处被释放->系统线程切换->主线程继续访问地址2f8, 但是此时该内存已被子线程释放,引起访问异常.
 
那这个问题要怎么样才能解决呢?
 
最简单的方法,超时时向主线程发消息,收到了才 line.add();
 
直接使用CreateThread虽然可以,但一些细节问题都要自己处理,很容易出错,出了也不容易找到。
 
多人接受答案了。
 
后退
顶部