Q
qqxk8199
Unregistered / Unconfirmed
GUEST, unregistred user!
各位朋友,最近我DLL方式实现TCP/IP通讯,进行数据的采集和发送.使用的是indy9中的TIdTCPClient和TIdTCPServer控件。为提高效率在通讯部分用线程方式来实现。但是在实际开发中出现了一个问题:在程序运行时当启动线程访问主表单中的IdTCPClient变量时提示出“非法访问错误”。然而之前编译却能通过。
开始时我怀疑整个单元都有问题,我另外新建了一个应用程序工程,而不是DLL,程序运行后发现线程能正常访问表单中的TIdTCPClient变量。这时我才意识到在可能是DLL中内存地址管理与应用程序不一样导致线程无法访问DLL中的表单。
晕~~~~这个如何是好啊!!
敬请高手指点啊。
以下是部分代码:
1、DLL出口函数:
//-----------------------------------------
//函数名称: ShowUpdateDialog
//功能: DLL插件调用入口函数
//参数: ACaption: 本窗体标题 ;
//返回: 操作结果 0:成功 ;1 失败;
//-----------------------------------------
function ShowUpdateDialog(AHandle:THandle; ACaptionChar; ):integer;stdCall;
var
frm_BG_monitor:Tfrm_BG_monitor;
isOK:integer;
is_OK:boolean;
//str_format_date:string;
Schedule_Time:integer;
begin
// 复制应用程序的句柄给DLL的TApplication对象。
Application.Handle :=AHandle;
frm_BG_monitor :=Tfrm_BG_monitor.Create(Application);
try
frm_BG_monitor.showmodal; //
except
frm_BG_monitor.Free;
end;
end;
2、实现单元:
unit Ufrm_BG_monitor;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,ActiveX, IdIPWatch, IdTCPServer, IdComponent, IdTCPConnection,
..........................................
type
//工作线程定义:
TClientHandleThread = class(TThread)
private
CommandStr:String;
protected
procedure Execute; override;
Public
constructor Create;
destructor Destroy; override;
end;
//主表单定义
Tfrm_BG_monitor = class(TForm)
IdAntiFreeze1: TIdAntiFreeze;
IdIPWatch1: TIdIPWatch;
IdThreadMgrPool1: TIdThreadMgrPool;
...
IdTCPClient1: TIdTCPClient; //主表单中的TIdTCPClient变量
IdTCPOnline: TIdTCPClient ; //主表单中的TIdTCPClient变量
private
{ ....................................... }
var
frm_BG_monitor: Tfrm_BG_monitor;
.................................................
ClientHandleThread: TClientHandleThread; //定义线程变量
implementation
uses {.........................}
{$R *.dfm}
{..............
................
}
constructor TClientHandleThread.Create();
begin
inherited Create(false);
FreeOnTerminate:=True;
Suspended := false;
end;
destructor TClientHandleThread.Destroy;
begin
inherited destroy;
end;
procedure TClientHandleThread.Execute;
var
Thesize:Integer;
ThtStr:String;
RsltStream: TMemoryStream;
begin
while not Terminated do
begin
//在此将发生“非法访问错误”!!!
if not (frm_BG_monitor.IdTCPOnline.Connected) then
begin
frm_BG_monitor.ToClientDisconnect; //在此将发生“非法访问错误”!!!
Break;
end
else
begin
try //从服务器端接收信息
S:=frm_BG_monitor.IdTCPOnline.ReadLn(EOL); //“非法访问错误”!!!
Thesize:=Strtoint(ThtStr);
if Thesize>0 then
begin
try
.........................................
Except
Break;
end;
end;
except
end;
end;
end;
end;
开始时我怀疑整个单元都有问题,我另外新建了一个应用程序工程,而不是DLL,程序运行后发现线程能正常访问表单中的TIdTCPClient变量。这时我才意识到在可能是DLL中内存地址管理与应用程序不一样导致线程无法访问DLL中的表单。
晕~~~~这个如何是好啊!!
敬请高手指点啊。
以下是部分代码:
1、DLL出口函数:
//-----------------------------------------
//函数名称: ShowUpdateDialog
//功能: DLL插件调用入口函数
//参数: ACaption: 本窗体标题 ;
//返回: 操作结果 0:成功 ;1 失败;
//-----------------------------------------
function ShowUpdateDialog(AHandle:THandle; ACaptionChar; ):integer;stdCall;
var
frm_BG_monitor:Tfrm_BG_monitor;
isOK:integer;
is_OK:boolean;
//str_format_date:string;
Schedule_Time:integer;
begin
// 复制应用程序的句柄给DLL的TApplication对象。
Application.Handle :=AHandle;
frm_BG_monitor :=Tfrm_BG_monitor.Create(Application);
try
frm_BG_monitor.showmodal; //
except
frm_BG_monitor.Free;
end;
end;
2、实现单元:
unit Ufrm_BG_monitor;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,ActiveX, IdIPWatch, IdTCPServer, IdComponent, IdTCPConnection,
..........................................
type
//工作线程定义:
TClientHandleThread = class(TThread)
private
CommandStr:String;
protected
procedure Execute; override;
Public
constructor Create;
destructor Destroy; override;
end;
//主表单定义
Tfrm_BG_monitor = class(TForm)
IdAntiFreeze1: TIdAntiFreeze;
IdIPWatch1: TIdIPWatch;
IdThreadMgrPool1: TIdThreadMgrPool;
...
IdTCPClient1: TIdTCPClient; //主表单中的TIdTCPClient变量
IdTCPOnline: TIdTCPClient ; //主表单中的TIdTCPClient变量
private
{ ....................................... }
var
frm_BG_monitor: Tfrm_BG_monitor;
.................................................
ClientHandleThread: TClientHandleThread; //定义线程变量
implementation
uses {.........................}
{$R *.dfm}
{..............
................
}
constructor TClientHandleThread.Create();
begin
inherited Create(false);
FreeOnTerminate:=True;
Suspended := false;
end;
destructor TClientHandleThread.Destroy;
begin
inherited destroy;
end;
procedure TClientHandleThread.Execute;
var
Thesize:Integer;
ThtStr:String;
RsltStream: TMemoryStream;
begin
while not Terminated do
begin
//在此将发生“非法访问错误”!!!
if not (frm_BG_monitor.IdTCPOnline.Connected) then
begin
frm_BG_monitor.ToClientDisconnect; //在此将发生“非法访问错误”!!!
Break;
end
else
begin
try //从服务器端接收信息
S:=frm_BG_monitor.IdTCPOnline.ReadLn(EOL); //“非法访问错误”!!!
Thesize:=Strtoint(ThtStr);
if Thesize>0 then
begin
try
.........................................
Except
Break;
end;
end;
except
end;
end;
end;
end;