近给公司做完了一个文件转换的工具,要让程序开机启动并且可以设置时间段
来执行,开始用的是timer,想想换了线程,追求技术创新嘛!
可是使用下来发现个问题:
我现在都是用类来写代码的,
我的问题是:
我的类是写作pub单元的,
线程只是 创建了类的对象
和调用了类的实例的执行方法,
结果问题出来了:发现代码还是在主线程中执行的!
也就是说多线程的效率根本没有体现出来!!
我研究了下同事的线程代码,发现他所有的代码执行都是在
线程的定义中执行的,就是说他的线程和主线程没有冲突。
我的线程因为 调用了 主线程代码区域的代码段。我几个疑问向高手们讨教:
1.线程中如何使用 对象 ,如果对象的类的定义在线程外部
是不是线程就失效了。
2.如何在线程内部使用对象?是不是要使用线程就要所有的代码写在线程的类的
代码定义区域?附上部分代码:
TScanDir = class //监视目录时 得到目录的文件的子目录的list
Filelist: THashedStringList; //文件信息list
protected
constructor Create();
destructor Destroy; override;
function init(Flistview: TListView): Boolean; //初始化
public
function Setitems: Boolean; //刷新ListView的数据
end;
Filesinfo = class
ID: string; //转换文件的 记录 ID
TARGET_FILE_SIZE: string[10]; //转换后的文件大小
end;
Trans = class
files : Filesinfo;
lvSuccessTrans: TListView; //成功日志的listview ,只传递不创建销毁更新数据库
function Getnow: string;
public
procedure SaveSql(res: Boolean);
property Nowtime: string read getNOw;
end;
TTransPDF = class
SaveTrans: Trans; // 转换完成后 更新数据库
listview: TListView;
function DeleteRecord: Boolean;
public
function TransFile: Boolean; //转换图片
end;
TWaitTrans = class(TSetlist)
protected
constructor Create(ads1: TADODataSet; listview: TListView);
destructor Destroy; override;
function setItems(TempListitem: TListItem): Boolean; override;
end; TTRansThread = class(TThread)
PauseTime: Integer;
List_Data: TWaitTrans;
TransPDF: TTransPDF;
constructor Create();
destructor Destroy; override;
private
function ShowDBSET: Boolean;
procedure createDBData; //监控数据库时从数据库中取出数据
procedure CreateDirData; //监控目录时从目录中得到数据
procedure create_listdata; //得到转换的数据
procedure Execute; override;
end;constructor TTRansThread.Create;
begin
TransPDF := TTransPDF.Create(frmMain.lvWaitTrans);
inherited Create(True);
end;procedure TTRansThread.create_listdata;
begin
if Serverini.Firsted.DataBase = '1' then
createDBData;
if Serverini.Firsted.DataBase = '0' then
CreateDirData;
end;procedure TTRansThread.createDBData;
var
ssql: string;
begin
if DMAdo.Contected then
begin
if not ExecSQL('select * from ' + dbsetini.TableName + ' where 1=0') then
begin
ErrorDialog('配置的数据库原文表不存在,请重新配置!');
if not ShowDBSET then Abort;
end;
end
else
if not ShowDBSET then Abort;
if not DMAdo.Contected then
begin
WarningDialog('数据库连接不上,请重新配置!');
Abort;
end;
if not ExecSQL('select * from ' + dbsetini.TableName + ' where 1=0') then
begin
ErrorDialog('配置的数据库原文表不存在,请重新配置!');
Abort;
end
else if not ExecSQL('select ' + Dbsetini.keyfield + ' from ' +
dbsetini.TableName + ' where 1=0') then
begin
ErrorDialog('配置的数据库的主键字段不存在,请重新配置!');
Abort;
end; List_Data := TWaitTrans.Create(frmMain.Ads_DOCUMENT, frmMain.lvWaitTrans);
List_Data.filebootpath := Serverini.Directory.WatchCatalog;
List_Data.display_view;
end;procedure TTRansThread.CreateDirData;
var
ScanDir: TScanDir;
begin
ScanDir := TScanDir.Create;
try
ScanDir.init(frmMain.lvWaitTrans);
ScanDir.Setitems;
finally
FreeAndNil(ScanDir);
end;
end;destructor TTRansThread.Destroy;
begin
FreeAndNil(List_Data);
FreeAndNil(TransPDF);
inherited;
end;procedure TTRansThread.Execute;
var
time: Integer;
res: Boolean;
begin
if Serverini.Firsted.ScanTime = '' then
time := 1
else
time := StrToInt(Serverini.Firsted.ScanTime);
// self.Synchronize(Self.trans);
while True do
begin
if TerminateD then Break;
try
frmMain.rzglyTransState.Caption := '转换中';
frmMain.IsTransed := True;
frmMain.rzglyTransState.ImageIndex := 2;
if TerminateD then Break;
create_listdata;
if TerminateD then Break;
res := TransPDF.TransFile;
finally
Sleep(time * 1000);
// Self.Suspend;
frmMain.rzglyTransState.Caption := '监控中';
frmMain.rzglyTransState.ImageIndex := 1;
frmMain.IsTransed := False;
end;
end;
end;
有同事说用 消息机制可以解决,不知道可以不?
来执行,开始用的是timer,想想换了线程,追求技术创新嘛!
可是使用下来发现个问题:
我现在都是用类来写代码的,
我的问题是:
我的类是写作pub单元的,
线程只是 创建了类的对象
和调用了类的实例的执行方法,
结果问题出来了:发现代码还是在主线程中执行的!
也就是说多线程的效率根本没有体现出来!!
我研究了下同事的线程代码,发现他所有的代码执行都是在
线程的定义中执行的,就是说他的线程和主线程没有冲突。
我的线程因为 调用了 主线程代码区域的代码段。我几个疑问向高手们讨教:
1.线程中如何使用 对象 ,如果对象的类的定义在线程外部
是不是线程就失效了。
2.如何在线程内部使用对象?是不是要使用线程就要所有的代码写在线程的类的
代码定义区域?附上部分代码:
TScanDir = class //监视目录时 得到目录的文件的子目录的list
Filelist: THashedStringList; //文件信息list
protected
constructor Create();
destructor Destroy; override;
function init(Flistview: TListView): Boolean; //初始化
public
function Setitems: Boolean; //刷新ListView的数据
end;
Filesinfo = class
ID: string; //转换文件的 记录 ID
TARGET_FILE_SIZE: string[10]; //转换后的文件大小
end;
Trans = class
files : Filesinfo;
lvSuccessTrans: TListView; //成功日志的listview ,只传递不创建销毁更新数据库
function Getnow: string;
public
procedure SaveSql(res: Boolean);
property Nowtime: string read getNOw;
end;
TTransPDF = class
SaveTrans: Trans; // 转换完成后 更新数据库
listview: TListView;
function DeleteRecord: Boolean;
public
function TransFile: Boolean; //转换图片
end;
TWaitTrans = class(TSetlist)
protected
constructor Create(ads1: TADODataSet; listview: TListView);
destructor Destroy; override;
function setItems(TempListitem: TListItem): Boolean; override;
end; TTRansThread = class(TThread)
PauseTime: Integer;
List_Data: TWaitTrans;
TransPDF: TTransPDF;
constructor Create();
destructor Destroy; override;
private
function ShowDBSET: Boolean;
procedure createDBData; //监控数据库时从数据库中取出数据
procedure CreateDirData; //监控目录时从目录中得到数据
procedure create_listdata; //得到转换的数据
procedure Execute; override;
end;constructor TTRansThread.Create;
begin
TransPDF := TTransPDF.Create(frmMain.lvWaitTrans);
inherited Create(True);
end;procedure TTRansThread.create_listdata;
begin
if Serverini.Firsted.DataBase = '1' then
createDBData;
if Serverini.Firsted.DataBase = '0' then
CreateDirData;
end;procedure TTRansThread.createDBData;
var
ssql: string;
begin
if DMAdo.Contected then
begin
if not ExecSQL('select * from ' + dbsetini.TableName + ' where 1=0') then
begin
ErrorDialog('配置的数据库原文表不存在,请重新配置!');
if not ShowDBSET then Abort;
end;
end
else
if not ShowDBSET then Abort;
if not DMAdo.Contected then
begin
WarningDialog('数据库连接不上,请重新配置!');
Abort;
end;
if not ExecSQL('select * from ' + dbsetini.TableName + ' where 1=0') then
begin
ErrorDialog('配置的数据库原文表不存在,请重新配置!');
Abort;
end
else if not ExecSQL('select ' + Dbsetini.keyfield + ' from ' +
dbsetini.TableName + ' where 1=0') then
begin
ErrorDialog('配置的数据库的主键字段不存在,请重新配置!');
Abort;
end; List_Data := TWaitTrans.Create(frmMain.Ads_DOCUMENT, frmMain.lvWaitTrans);
List_Data.filebootpath := Serverini.Directory.WatchCatalog;
List_Data.display_view;
end;procedure TTRansThread.CreateDirData;
var
ScanDir: TScanDir;
begin
ScanDir := TScanDir.Create;
try
ScanDir.init(frmMain.lvWaitTrans);
ScanDir.Setitems;
finally
FreeAndNil(ScanDir);
end;
end;destructor TTRansThread.Destroy;
begin
FreeAndNil(List_Data);
FreeAndNil(TransPDF);
inherited;
end;procedure TTRansThread.Execute;
var
time: Integer;
res: Boolean;
begin
if Serverini.Firsted.ScanTime = '' then
time := 1
else
time := StrToInt(Serverini.Firsted.ScanTime);
// self.Synchronize(Self.trans);
while True do
begin
if TerminateD then Break;
try
frmMain.rzglyTransState.Caption := '转换中';
frmMain.IsTransed := True;
frmMain.rzglyTransState.ImageIndex := 2;
if TerminateD then Break;
create_listdata;
if TerminateD then Break;
res := TransPDF.TransFile;
finally
Sleep(time * 1000);
// Self.Suspend;
frmMain.rzglyTransState.Caption := '监控中';
frmMain.rzglyTransState.ImageIndex := 1;
frmMain.IsTransed := False;
end;
end;
end;
有同事说用 消息机制可以解决,不知道可以不?
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货