Indy IdThreadComponent 线程研究
前几天在开发数据实时解析功能模块的时候,发现解析数据量巨大,特别耗时,程序一跑起来界面假死。
为了优化用户体验,采用了Indy 自带的IdThreadComponent控件,完美的解决了此问题。
下面就IdThreadComponent一些关键属性和方法做如下记录:
1:IdThreadComponent属性
这里主要记录一下Active、Priority和StopMode属性。
Active:默认False,当需要令IdThreadComponent控件生效时,置为True;
Priority:为避免线程之间相互冲突,选择Normal,让系统自带分配优先级;
StopMode:这里分为Terminate和Suspend两种,Terminate为强行终止,Suspend为延缓、等待终止。
2:IdThreadComponent方法
TIdThreadComponent用的是观察者模式,所有这里的事件都是回调事件。
一般比较耗时的操作放在OnRun中执行。
事件执行顺序如下:
On Before Execute;
On Before Run;
On Run;
On Stopped;
On After Run;
On After Execute;
3:通过如下Demo进行说明
需要说明一下:
在线程里不可以直接操作界面上的控件,因为有时候控件被销毁了而线程还在运行,这时直接操作会抛AV异常,所以在TIdThreadComponent回调事件中,如果有使用到控件的,必须先做控件是否为空的判断。
界面如下:
代码如下:
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.