Delphi - 闲来无事,自己写个Timer玩玩(多线程Timer)

明天去坐火车,回家,今天就没有事做,本来在弄一个跨进程获取其他程序里面组件,如ListView,ListBox,Button等的信息,突然有个想法自己写个Timer,不用SetTimer函数,我们自己用个多线程也正好实现这个.反正前段时间多线程也弄得比较多,本来想单独讲讲的,现在就用个例子来说明吧.
写成一个控件:utTimer.pas


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

unit utTimer;

interface

uses

  Windows,SysUtils,Classes;

type

  THuangJackyTimerThread = class;

  THuangJackyTimer = class(TComponent)

  private

    FTimeInterval:Integer;

    FOnTimerDo:TNotifyEvent;

    FTimerThread:THuangJackyTimerThread;

    FEnable:Boolean;

    procedure SetEnable(bBool:Boolean);

    procedure SetTimeInterval(aValue:Integer);

    procedure StopThread;

    procedure StartThread;

  public

    constructor Create(AOwner: TComponent); override;

    destructor Destroy; override;

  published

    property TimeInterval:Integer  read FTimeInterval write SetTimeInterval;

    property OnTimerDo:TNotifyEvent  read FOnTimerDo write FOnTimerDo;

    property Enable:Boolean  read FEnable write SetEnable;

  end;

  THuangJackyTimerThread = class(TThread)

  private

    FTimer:THuangJackyTimer;

    FTerminateHandle,FExitHandle,FStartHandle,FStopHandle:Cardinal;

    procedure DoTimerEvent;

  protected

    procedure Execute;override;

  public

    constructor Create(AOwner: THuangJackyTimer);

    destructor Destroy; override;

  end;

procedure Register;

implementation

procedure Register;

begin

  RegisterComponents(‘HuangJacky‘,[THuangJackyTimer]);

end;

{ THuangJackyTimer }

constructor THuangJackyTimer.Create(AOwner: TComponent);

begin

  inherited;

  FTimeInterval:=1000;

  FTimerThread:=THuangJackyTimerThread.Create(Self);

  FTimerThread.Resume;

end;

destructor THuangJackyTimer.Destroy;

begin

  SetEvent(FTimerThread.FTerminateHandle);

  WaitForSingleObject(FTimerThread.FExitHandle,5000);

  FTimerThread.Free;

  inherited;

end;

procedure THuangJackyTimer.SetEnable(bBool: Boolean);

begin

  if Enable = bBool then

    Exit;

  if csDesigning in ComponentState then

    Exit;

  if Enable then

  begin

    StopThread;

    FEnable:=False;

  end

  else

  begin

    StartThread;

    FEnable:=True;

  end;

end;

procedure THuangJackyTimer.SetTimeInterval(aValue: Integer);

begin

  if FTimeInterval = aValue then

    Exit;

  InterlockedExchange(FTimeInterval,aValue);

end;

procedure THuangJackyTimer.StartThread;

begin

  SetEvent(FTimerThread.FStartHandle);

end;

procedure THuangJackyTimer.StopThread;

begin

  SetEvent(FTimerThread.FStopHandle)

end;

{ THuangJackyTimerThread }

constructor THuangJackyTimerThread.Create(AOwner: THuangJackyTimer);

var

  sTmp,sTmp1:string;

begin

  inherited Create(True);

  Assert(Assigned(AOwner));

  //自己创建,自己释放,这样能保证100%不内存泄露,个人习惯

  FreeOnTerminate:=False;

  FTimer:=AOwner;

  sTmp:=FTimer.Name;

  sTmp1:=DateTimeToStr(Now());

  FTerminateHandle:=CreateEvent(nil,True,False,PChar(sTmp + sTmp1 + ‘T‘));

  Assert(FTerminateHandle<>0);

  //用这个Event来通知主线程:Timer线程已经执行完了

  FExitHandle:=CreateEvent(nil,True,False,PChar(sTmp + sTmp1 + ‘E‘));

  Assert(FExitHandle<>0);

  FStartHandle:=CreateEvent(nil,True,False,PChar(sTmp + sTmp1 +‘Sa‘));

  Assert(FStartHandle<>0);

  FStopHandle:=CreateEvent(nil,True,False,PChar(sTmp + sTmp1 + ‘So‘));

  Assert(FStopHandle<>0);

end;

destructor THuangJackyTimerThread.Destroy;

begin

   CloseHandle(FStopHandle);

   CloseHandle(FStartHandle);

   CloseHandle(FExitHandle);

   CloseHandle(FTerminateHandle);

  inherited;

end;

procedure THuangJackyTimerThread.DoTimerEvent;

begin

  if Assigned(FTimer.OnTimerDo) then

    FTimer.OnTimerDo(FTimer);

end;

procedure THuangJackyTimerThread.Execute;

var

  Waits1:array[0..2] of Cardinal;

  Waits2:array[0..1] of Cardinal;

  procedure DoTerminate;

  begin

    ResetEvent(FTerminateHandle);

    Terminate;

  end;

begin

  Waits1[0]:=FStartHandle;

  Waits1[1]:=FTerminateHandle;

  Waits1[2]:=FStopHandle;

  Waits2[0]:=FStopHandle;

  Waits2[1]:=FTerminateHandle;

  //循环等待.

  while not Terminated do

    //每一次Wait后我们都需要判断下Terminate,不然在你等待的时候,线程就被Terminate了.

    //不过不判断也不要紧

    //因为Terminate只是将Terminated设置成True.

    //也就是如果不判断,就多运行一次.

    //但是这个例子里面因为内层也有一个While循环,所以必须判断

    case WaitForMultipleObjects(3,@Waits1,False,INFINITE) of

      WAIT_OBJECT_0 + 0:

        begin

          ResetEvent(FStartHandle);

          if Terminated then

            Break;

          while True do

          begin

            case WaitForMultipleObjects(2,@Waits2,False,FTimer.TimeInterval) of

              WAIT_OBJECT_0 + 0:

                begin

                  ResetEvent(FStopHandle);

                  Break

                end;

              WAIT_OBJECT_0 + 1:

                begin

                  DoTerminate;

                  Break;

                end;

            end;

            if Terminated then

              Break;

            //执行Timer事件.

            Synchronize(DoTimerEvent);

          end;

        end;

      WAIT_OBJECT_0 + 1:

        DoTerminate;

      WAIT_OBJECT_0 + 2:

        ResetEvent(FStopHandle);

    end;

  SetEvent(FExitHandle);

end;

end.

两百行的代码,比较简单,就是一个线程在循环等待事件,然后相应的事件做相应的事.
其实主要是想说如何使用线程,我不喜欢将线程的FreeOnTerminate设置为True,因为感觉不安全,心里不踏实呀.
测试例子:Unit1.pas


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

unit Unit1;

interface

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs,utTimer;

type

  TForm1 = class(TForm)

    procedure FormCreate(Sender: TObject);

  private

    { Private declarations }

    Timer:THuangJackyTimer;

    III:Integer;

    procedure DoTimer(S:TObject);

  public

    { Public declarations }

  end;

var

  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DoTimer(S: TObject);

begin

//这个Timer不存在重入的情况,所以不需要先设置Enable为True

  Caption:=IntToStr(III);

  Inc(III);

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

  Timer:=THuangJackyTimer.Create(Self);

  Timer.TimeInterval:=2000;

  Timer.OnTimerDo:=DoTimer;

  Timer.Enable:=True;

end;

end.

D7和D2010上面都测试了一下,米有发现问题.
如果有什么问题欢迎拍砖.哈哈

http://www.cnblogs.com/huangjacky/archive/2010/02/10/1667217.html

时间: 2024-10-27 08:00:31

Delphi - 闲来无事,自己写个Timer玩玩(多线程Timer)的相关文章

发现个delphi调用vc写的Dll中包含pchar参数报错奇怪现象

发现个delphi调用vc写的Dll中包含pchar参数奇怪现象 procedure中的第一行语句不能直接调用DLL的函数,否则会运行错,在之前任意加上条语句就不报错了奇怪! vc的DLL源码地址 http://blog.csdn.net/lqena/article/details/46357165 Delphi源码如下: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Co

Forms.Timer、Timers.Timer、Threading.Timer的研究

.NET Framework里面提供了三种Timer System.Windows.Forms.Timer System.Timers.Timer System.Threading.Timer 一.System.Windows.Forms.Timer 1.基于Windows消息循环,用事件方式触发,在界面线程执行:是使用得比较多的Timer,Timer Start之后定时(按设定的Interval)调用挂接在Tick事件上的EvnetHandler.在这种Timer的EventHandler中可

C#-Forms.Timer、Timers.Timer、Threading.Timer的比较和使用

在.NET Framework里面提供了三种Timer ① System.Windows.Forms.Timer ② System.Timers.Timer ③ System.Threading.Timer 一.System.Windows.Forms.Timer 1.基于Windows消息循环,用事件方式触发,在界面线程执行:是使用得比较多的Timer,Timer Start之后定时(按设定的Interval)调用挂接在Tick事件上的EvnetHandler.在这种Timer的EventHa

delphi 线程教学第四节:多线程类的改进

第四节:多线程类的改进 1.需要改进的地方 a) 让线程类结束时不自动释放,以便符合 delphi 的用法.即 FreeOnTerminate:=false; b) 改造 Create 的参数,让它适合访问 COM 组件.如:在线程时空中能够创建 TAdoConnection; c) 设计一个接口能将一个过程( procedure )塞到线程时空中去运行的功能,这样,不必每次重载 Execute 函数. d) 设计一个输出信息的接口 下一节,将讲解如何用多个线程同时执行相同的任务 改进后的多线程

Matlab中用Timer实现多线程机制

Matlab中Timer的使用 鉴于Matlab 中缺乏多线程机制,使用Timer 无疑是一个很重要的工具,Matlab 中Timer 是一个Java 对象. (1) Timer 的定义  t=timer(); 设置属性: eg.  set(t,'Name','your_timer_name'); 当然可以一次性设置完成: 例如: TaskTimer=timer(... 'Name','FebirdTimer',... 'TimerFcn',@ExecuteTask,... 'ErrorFcn'

Delphi调用C++写的dll示例

最近做一个读市民卡的项目,读卡器公司提供的读市民卡dll是用C++写的. 下面记录一些自己的心得,供需要的朋友参考. 声明dll函数要加上stdcall关键字,否则可能会报地址非法的错误. 代码: unit cMain; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, ADODB, StdCtrls, ComCtrls,ActiveX, E

「闲来无事」写了个类似于微博的效果

* {margin: 0;padding: 0;font-size: 20px;font-family: 'microsoft yahei';} .clear {overflow: hidden;height: 0;clear: both;} textarea {width: 500px;height: 150px;border:1px #cecece solid;resize: none;float: left;} #btn {float: left;background: -webkit-l

[叩响C#之门]写给初学者:多线程系列(七)——互锁(Interlocked类)

前言:我第一次接触“线程”的概念时,觉得它深奥难懂,看了好多本书,花了很长时间才领悟到它的真谛.现在我就以一个初学者的心态,把我所理解的“多线程”描述给大家.这一次是系列文章,比较完整的展示与线程相关的基本概念.希望对初学者有所帮助.语言比较精炼,有些地方需要反复阅读. 目录(欲看前面的章节,请点击下面的链接 ) 第21章 多 线 程 21.1 线程的概念 21.2 Thread类 21.3 线程的优先级 21.4 线程的插入 21.5 线程的状态 21.6 线程的同步 21.6.1 线程同步的

自己写个list玩玩

/*如果采用单向链表,end()函数如何表示? *所以必须得采用循环链表的方式? * */ #ifndef LIST #define LIST #include<iostream> using namespace std; //声明 template <class T> struct Node{ T data; struct Node<T>* next; Node(struct Node<T>* p):data(p->data),next(p->