Delphi

Delphi

Indy IdThreadComponent 线程研究

前几天在开发数据实时解析功能模块的时候,发现解析数据量巨大,特别耗时,程序一跑起来界面假死。

为了优化用户体验,采用了Indy 自带的IdThreadComponent控件,完美的解决了此问题。

下面就IdThreadComponent一些关键属性和方法做如下记录:

1:IdThreadComponent属性

这里主要记录一下Active、Priority和StopMode属性。

Active:默认False,当需要令IdThreadComponent控件生效时,置为True;

Priority:为避免线程之间相互冲突,选择Normal,让系统自带分配优先级;

StopMode:这里分为Terminate和Suspend两种,Terminate为强行终止,Suspend为延缓、等待终止。

Delphi

2:IdThreadComponent方法

TIdThreadComponent用的是观察者模式,所有这里的事件都是回调事件。

一般比较耗时的操作放在OnRun中执行。

事件执行顺序如下:

On Before Execute;

On Before Run;

On Run; 

On Stopped;

On After Run;

On After Execute;

Delphi

3:通过如下Demo进行说明

需要说明一下:

在线程里不可以直接操作界面上的控件,因为有时候控件被销毁了而线程还在运行,这时直接操作会抛AV异常,所以在TIdThreadComponent回调事件中,如果有使用到控件的,必须先做控件是否为空的判断。

界面如下:

Delphi

代码如下:

  1 unit uMain;
  2 
  3 interface
  4 
  5 uses
  6   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7   Dialogs, RzButton, StdCtrls, RzEdit, IdBaseComponent, IdThreadComponent;
  8 
  9 type
 10   TMainFrm = class(TForm)
 11     IDTrd: TIdThreadComponent;
 12     mmMsg: TRzMemo;
 13     btnStart: TRzBitBtn;
 14     btnStop: TRzBitBtn;
 15     btnTerminal: TRzBitBtn;
 16     procedure btnStartClick(Sender: TObject);
 17     procedure IDTrdRun(Sender: TIdCustomThreadComponent);
 18     procedure IDTrdBeforeExecute(Sender: TIdCustomThreadComponent);
 19     procedure IDTrdAfterExecute(Sender: TIdCustomThreadComponent);
 20     procedure btnStopClick(Sender: TObject);
 21     procedure btnTerminalClick(Sender: TObject);
 22     procedure IDTrdAfterRun(Sender: TIdCustomThreadComponent);
 23     procedure IDTrdBeforeRun(Sender: TIdCustomThreadComponent);
 24     procedure IDTrdStopped(Sender: TIdCustomThreadComponent);
 25   private
 26     { Private declarations }
 27   public
 28     { Public declarations }
 29   end;
 30 
 31 var
 32   MainFrm: TMainFrm;
 33 
 34 implementation
 35 
 36 {$R *.dfm}
 37 
 38 procedure TMainFrm.btnStartClick(Sender: TObject);
 39 begin
 40   IDTrd.Active := True;
 41 end;
 42 
 43 procedure TMainFrm.IDTrdRun(Sender: TIdCustomThreadComponent);
 44 var
 45   I: Integer;
 46 begin
 47   for I := 1 to 100 do
 48   begin
 49     mmMsg.Lines.Add(IntToStr(I)); //模拟耗时操作
 50   end;
 51   //在线程里不可以直接操作界面控件,有时候控件被销毁了而线程还在运行,
 52   //此时就会报AV异常,
 53   //所以在TIdThreadComponent回调事件中有使用到控件的,必须添加控件是否为空判断
 54 end;
 55 
 56 procedure TMainFrm.IDTrdBeforeExecute(Sender: TIdCustomThreadComponent);
 57 begin
 58   if Assigned(mmMsg) then
 59   begin
 60     mmMsg.Lines.Add('Before Execute');
 61   end;
 62 end;
 63 
 64 procedure TMainFrm.IDTrdAfterExecute(Sender: TIdCustomThreadComponent);
 65 begin
 66   if Assigned(mmMsg) then
 67   begin
 68     mmMsg.Lines.Add('After Execute');
 69   end;
 70 end;
 71 
 72 procedure TMainFrm.btnStopClick(Sender: TObject);
 73 begin
 74   IDTrd.Stop;
 75 end;
 76 
 77 procedure TMainFrm.btnTerminalClick(Sender: TObject);
 78 begin
 79   IDTrd.Terminate;
 80 end;
 81 
 82 procedure TMainFrm.IDTrdAfterRun(Sender: TIdCustomThreadComponent);
 83 begin
 84   if Assigned(mmMsg) then
 85   begin
 86     mmMsg.Lines.Add('After Run');
 87   end;
 88 end;
 89 
 90 procedure TMainFrm.IDTrdBeforeRun(Sender: TIdCustomThreadComponent);
 91 begin
 92   if Assigned(mmMsg) then
 93   begin
 94     mmMsg.Lines.Add('Before Run');
 95   end;
 96 end;
 97 
 98 procedure TMainFrm.IDTrdStopped(Sender: TIdCustomThreadComponent);
 99 begin
100   if Assigned(mmMsg) then
101   begin
102     mmMsg.Lines.Add('On Stopped');
103   end;
104 end;
105 
106 end.

  作者:Jeremy.Wu
  出处:https://www.cnblogs.com/jeremywucnblog/
  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。