近给公司做完了一个文件转换的工具,要让程序开机启动并且可以设置时间段
来执行,开始用的是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;
有同事说用 消息机制可以解决,不知道可以不?

解决方案 »

  1.   

    你线程里面做了太多需要同步执行的操作,也就是太多地方是直接操作主线程的 VCL 资源的。我不知道你“追求技术创新”是为了什么目的,可是没有必要就不用把这些与主线程有着千丝万缕的联系的代码放在线程里面去运行。如果你坚持要用线程处理,那么就把这些代码从主线程使用的模块中分离出来。最后就把处理的结果以共享数据或者消息的方法传回主线程吧。
      

  2.   

    delphi的vcl能 直接支持多线程 就好了
      

  3.   

    用VCL作界面,在线程使用共享变量。
      

  4.   

    你在线程中直接执行frmMain.rzglyTransState.Caption := '转换中'是有问题的,需要用到同步,另外你的这个代码没必要用线程,得不偿失。