IdThreadComponent.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.13 9/30/2004 2:26:04 PM BGooijen
  18. wrong property was referenced
  19. Rev 1.12 2004.02.03 4:17:12 PM czhower
  20. For unit name changes.
  21. Rev 1.11 2004.01.20 10:03:38 PM czhower
  22. InitComponent
  23. Rev 1.10 09.11.2003 14:05:52 ARybin
  24. AV
  25. Rev 1.9 08.11.2003 20:03:20 ARybin
  26. run-time active bug
  27. Rev 1.8 10/15/2003 8:48:58 PM DSiders
  28. Added resource strings for exceptions raised when setting thread component
  29. properties.
  30. Rev 1.7 2003.10.11 9:58:04 PM czhower
  31. Several bug fixes
  32. Rev 1.6 2003.10.11 5:51:54 PM czhower
  33. -VCL fixes for servers
  34. -Chain suport for servers (Super core)
  35. -Scheduler upgrades
  36. -Full yarn support
  37. Rev 1.5 2003.09.30 7:48:02 PM czhower
  38. Fixed Loop and ThreadName
  39. Rev 1.4 9/18/2003 07:40:52 PM JPMugaas
  40. Removed IdGlobal.
  41. Rev 1.3 9/16/2003 04:47:22 PM JPMugaas
  42. Made some code follow the Indy conventions so it's easier to debug.
  43. Rev 1.2 2003.07.01 4:14:38 PM czhower
  44. ThreadName and Loop added. Other bugs fixed.
  45. Rev 1.1 06.03.2003 12:16:52 ARybin
  46. adapted for new IdThread
  47. Rev 1.0 11/13/2002 08:03:06 AM JPMugaas
  48. 2002-05-03 -Andrew P.Rybin
  49. -Stéphane Grobéty (Fulgan) suggestion: component is Data owner, don't FreeAndNIL Data property
  50. -special TThread.OnTerminate support (it is sync-event)
  51. 2002-05-23 -APR
  52. -right support for Thread terminate
  53. }
  54. unit IdThreadComponent;
  55. {
  56. UnitName: IdThreadComponent
  57. Author: Andrew P.Rybin [[email protected]]
  58. Creation: 12.03.2002
  59. Version: 0.1.0
  60. Purpose:
  61. History: Based on my TmcThread
  62. }
  63. interface
  64. {$I IdCompilerDefines.inc}
  65. //Put FPC into Delphi mode
  66. uses
  67. Classes,
  68. IdBaseComponent, IdException, IdGlobal, IdThread, SysUtils;
  69. const
  70. IdThreadComponentDefaultPriority = tpNormal;
  71. IdThreadComponentDefaultStopMode = smTerminate;
  72. type
  73. TIdThreadComponent = class;
  74. TIdExceptionThreadComponentEvent = procedure(Sender: TIdThreadComponent; AException: Exception) of object;
  75. TIdExceptionThreadComponentEventEx = procedure(Sender: TIdThreadComponent; AException: Exception; var VHandled: Boolean) of object;
  76. TIdNotifyThreadComponentEvent = procedure(Sender: TIdThreadComponent) of object;
  77. //TIdSynchronizeThreadComponentEvent = procedure(Sender: TIdThreadComponent; AData: Pointer) of object;
  78. TIdThreadComponent = class(TIdBaseComponent)
  79. protected
  80. FActive: Boolean;
  81. FLoop: Boolean;
  82. FPriority : TIdThreadPriority;
  83. FStopMode : TIdThreadStopMode;
  84. FThread: TIdThread;
  85. FThreadName: string;
  86. //
  87. FOnAfterExecute: TIdNotifyThreadComponentEvent;
  88. FOnAfterRun: TIdNotifyThreadComponentEvent;
  89. FOnBeforeExecute: TIdNotifyThreadComponentEvent;
  90. FOnBeforeRun: TIdNotifyThreadComponentEvent;
  91. FOnCleanup: TIdNotifyThreadComponentEvent;
  92. FOnException: TIdExceptionThreadComponentEvent;
  93. FOnRun: TIdNotifyThreadComponentEvent;
  94. FOnStopped: TIdNotifyThreadComponentEvent;
  95. FOnTerminate: TIdNotifyThreadComponentEvent;
  96. FOnHandleRunException: TIdExceptionThreadComponentEventEx;
  97. //
  98. {$IFDEF INT_THREAD_PRIORITY}
  99. procedure DefineProperties(Filer: TFiler); override;
  100. procedure ReadPriority(Reader: TReader);
  101. procedure WritePriority(Writer: TWriter);
  102. {$ENDIF}
  103. procedure DoAfterExecute; virtual;
  104. procedure DoAfterRun; virtual;
  105. procedure DoBeforeExecute; virtual;
  106. procedure DoBeforeRun; virtual;
  107. procedure DoCleanup; virtual;
  108. procedure DoException(AThread: TIdThread; AException: Exception); virtual; //thev
  109. function DoHandleRunException(AException: Exception): Boolean; virtual;
  110. procedure DoRun; virtual;
  111. procedure DoStopped(AThread: TIdThread); virtual; //thev
  112. procedure DoTerminate(Sender: TObject); virtual; //thev
  113. function GetActive: Boolean;
  114. {$IFDEF USE_OBJECT_ARC}
  115. // When ARC is enabled, object references MUST be valid objects.
  116. // It is common for users to store non-object values, though, so
  117. // we will provide separate properties for those purposes
  118. //
  119. // TODO; use TValue instead of separating them
  120. //
  121. function GetDataObject: TObject;
  122. function GetDataValue: PtrInt;
  123. {$ELSE}
  124. function GetData: TObject;
  125. {$ENDIF}
  126. function GetHandle: TIdThreadHandle;
  127. function GetPriority: TIdThreadPriority;
  128. function GetReturnValue: Integer;
  129. function GetStopMode: TIdThreadStopMode;
  130. function GetStopped: Boolean;
  131. function GetSuspended: Boolean;
  132. function GetTerminatingException: string;
  133. function GetTerminatingExceptionClass: TClass;
  134. function GetTerminated: Boolean;
  135. procedure InitComponent; override;
  136. function IsRunning: Boolean;
  137. procedure Loaded; override;
  138. procedure SetActive(const AValue: Boolean); virtual;
  139. {$IFDEF USE_OBJECT_ARC}
  140. procedure SetDataObject(const AValue: TObject);
  141. procedure SetDataValue(const AValue: PtrInt);
  142. {$ELSE}
  143. procedure SetData(const AValue: TObject);
  144. {$ENDIF}
  145. procedure SetLoop(const AValue: Boolean);
  146. procedure SetThreadName(const AValue: string);
  147. procedure SetOnTerminate(const AValue: TIdNotifyThreadComponentEvent);
  148. procedure SetPriority(const AValue: TIdThreadPriority);
  149. procedure SetReturnValue(const AValue: Integer);
  150. procedure SetStopMode(const AValue: TIdThreadStopMode);
  151. public
  152. destructor Destroy; override;
  153. procedure Start; virtual;
  154. procedure Stop; virtual;
  155. procedure Synchronize(AMethod: TThreadMethod);
  156. procedure Terminate; virtual;
  157. procedure TerminateAndWaitFor; virtual;
  158. function WaitFor: UInt32;
  159. // Properties
  160. {$IFDEF USE_OBJECT_ARC}
  161. property DataObject: TObject read GetDataObject write SetDataObject;
  162. property DataValue: PtrInt read GetDataValue write SetDataValue;
  163. {$ELSE}
  164. property Data: TObject read GetData write SetData;
  165. {$ENDIF}
  166. property Handle: TIdThreadHandle read GetHandle;
  167. property ReturnValue: Integer read GetReturnValue write SetReturnValue;
  168. property Stopped: Boolean read GetStopped;
  169. property Suspended: Boolean read GetSuspended;
  170. property TerminatingException: string read GetTerminatingException;
  171. property TerminatingExceptionClass: TClass read GetTerminatingExceptionClass;
  172. property Terminated: Boolean read GetTerminated;
  173. {$IFDEF INT_THREAD_PRIORITY}
  174. property Priority: TIdThreadPriority read GetPriority write SetPriority;
  175. {$ENDIF}
  176. published
  177. property Active: Boolean read GetActive write SetActive;
  178. property Loop: Boolean read FLoop write SetLoop;
  179. {$IFNDEF INT_THREAD_PRIORITY}
  180. property Priority: TIdThreadPriority read GetPriority write SetPriority;
  181. {$ENDIF}
  182. property StopMode: TIdThreadStopMode read GetStopMode write SetStopMode;
  183. property ThreadName: string read FThreadName write SetThreadName;
  184. // Events
  185. property OnAfterExecute: TIdNotifyThreadComponentEvent read FOnAfterExecute write FOnAfterExecute;
  186. property OnAfterRun: TIdNotifyThreadComponentEvent read FOnAfterRun write FOnAfterRun;
  187. property OnBeforeExecute: TIdNotifyThreadComponentEvent read FOnBeforeExecute write FOnBeforeExecute;
  188. property OnBeforeRun: TIdNotifyThreadComponentEvent read FOnBeforeRun write FOnBeforeRun;
  189. property OnCleanup: TIdNotifyThreadComponentEvent read FOnCleanup write FOnCleanup;
  190. property OnException: TIdExceptionThreadComponentEvent read FOnException write FOnException;
  191. property OnHandleRunException: TIdExceptionThreadComponentEventEx
  192. read FOnHandleRunException write FOnHandleRunException;
  193. property OnRun: TIdNotifyThreadComponentEvent read FOnRun write FOnRun;
  194. property OnStopped: TIdNotifyThreadComponentEvent read FOnStopped
  195. write FOnStopped;
  196. property OnTerminate: TIdNotifyThreadComponentEvent read FOnTerminate
  197. write SetOnTerminate;
  198. end;
  199. //For Component-writers ONLY!
  200. TIdThreadEx = class(TIdThread)
  201. protected
  202. FThreadComponent: TIdThreadComponent;
  203. //
  204. procedure AfterRun; override;
  205. procedure AfterExecute; override;
  206. procedure BeforeExecute; override;
  207. procedure BeforeRun; override;
  208. procedure Cleanup; override;
  209. function HandleRunException(AException: Exception): Boolean; override;
  210. procedure Run; override;
  211. public
  212. constructor Create(AThreadComponent: TIdThreadComponent); reintroduce;
  213. end;
  214. implementation
  215. uses
  216. IdResourceStringsCore;
  217. { TIdThreadEx }
  218. procedure TIdThreadEx.AfterExecute;
  219. begin
  220. try
  221. FThreadComponent.DoAfterExecute;
  222. finally
  223. FThreadComponent.FActive := FALSE;
  224. end;
  225. end;
  226. procedure TIdThreadEx.AfterRun;
  227. begin
  228. FThreadComponent.DoAfterRun;
  229. end;
  230. procedure TIdThreadEx.BeforeExecute;
  231. begin
  232. FThreadComponent.DoBeforeExecute;
  233. end;
  234. procedure TIdThreadEx.BeforeRun;
  235. begin
  236. FThreadComponent.DoBeforeRun;
  237. end;
  238. procedure TIdThreadEx.Cleanup;
  239. begin
  240. inherited Cleanup;
  241. FThreadComponent.DoCleanup;
  242. end;
  243. constructor TIdThreadEx.Create(AThreadComponent: TIdThreadComponent);
  244. begin
  245. inherited Create(True, AThreadComponent.Loop, iif(AThreadComponent.ThreadName = ''
  246. , AThreadComponent.Name, AThreadComponent.ThreadName));
  247. Exclude(FOptions, itoDataOwner); //TIdThreadComponent is data owner
  248. FThreadComponent := AThreadComponent;
  249. FOnException := FThreadComponent.DoException;
  250. FOnStopped := FThreadComponent.DoStopped;
  251. end;
  252. function TIdThreadEx.HandleRunException(AException: Exception): Boolean;
  253. begin
  254. Result := FThreadComponent.DoHandleRunException(AException);
  255. end;
  256. procedure TIdThreadEx.Run;
  257. begin
  258. FThreadComponent.DoRun;
  259. end;
  260. { TIdThreadComponent }
  261. {$IFDEF INT_THREAD_PRIORITY}
  262. procedure TIdThreadComponent.DefineProperties(Filer: TFiler);
  263. begin
  264. inherited;
  265. Filer.DefineProperty('Priority', ReadPriority, WritePriority, FPriority <> tpNormal);
  266. end;
  267. procedure TIdThreadComponent.ReadPriority(Reader: TReader);
  268. const
  269. PriorityStrings: array[0..6] of string = ('tpIdle', 'tpLowest', 'tpLower', 'tpNormal', 'tpHigher', 'tpHighest', 'tpTimeCritical'); {do not localize}
  270. var
  271. Value: Integer;
  272. begin
  273. if Reader.NextValue = vaIdent then
  274. begin
  275. // an older DFM that stored TThreadPriority as enum value names is being read, so convert to integer ...
  276. case PosInStrArray(Reader.ReadIdent, PriorityStrings, False) of
  277. 0: Value := tpIdle;
  278. 1: Value := tpLowest;
  279. 2: Value := tpLower;
  280. 3: Value := tpNormal;
  281. 4: Value := tpHigher;
  282. 5: Value := tpHighest;
  283. 6: Value := tpTimeCritical;
  284. else
  285. Value := tpNormal;
  286. end;
  287. end else
  288. begin
  289. Value := Reader.ReadInteger;
  290. if Value < -20 then begin
  291. Value := -20;
  292. end
  293. else if Value > 19 then begin
  294. Value := 19;
  295. end;
  296. end;
  297. FPriority := Value;
  298. end;
  299. procedure TIdThreadComponent.WritePriority(Writer: TWriter);
  300. begin
  301. Writer.WriteInteger(FPriority);
  302. end;
  303. {$ENDIF}
  304. procedure TIdThreadComponent.DoAfterExecute;
  305. begin
  306. if Assigned(FOnAfterExecute) then
  307. begin
  308. FOnAfterExecute(Self);
  309. end;
  310. end;
  311. procedure TIdThreadComponent.DoAfterRun;
  312. begin
  313. if Assigned(FOnAfterRun) then
  314. begin
  315. FOnAfterRun(Self);
  316. end;
  317. end;
  318. procedure TIdThreadComponent.DoBeforeExecute;
  319. begin
  320. if Assigned(FOnBeforeExecute) then
  321. begin
  322. FOnBeforeExecute(Self);
  323. end;
  324. end;
  325. procedure TIdThreadComponent.DoBeforeRun;
  326. begin
  327. if Assigned(FOnBeforeRun) then
  328. begin
  329. FOnBeforeRun(Self);
  330. end;
  331. end;
  332. procedure TIdThreadComponent.DoCleanup;
  333. begin
  334. if Assigned(FOnCleanup) then
  335. begin
  336. FOnCleanup(Self);
  337. end;
  338. end;
  339. destructor TIdThreadComponent.Destroy;
  340. begin
  341. {FThread.TerminateAndWaitFor;}
  342. //make sure thread is not active before we attempt to destroy it
  343. if Assigned(FThread) then begin
  344. FThread.Terminate;
  345. FThread.Start;//resume for terminate
  346. end;
  347. IdDisposeAndNil(FThread);
  348. inherited Destroy;
  349. end;
  350. procedure TIdThreadComponent.DoException(AThread: TIdThread; AException: Exception);
  351. begin
  352. if Assigned(FOnException) then begin
  353. FOnException(Self, AException);
  354. end;
  355. end;
  356. function TIdThreadComponent.DoHandleRunException(AException: Exception): Boolean;
  357. begin
  358. Result := False;//not handled
  359. if Assigned(FOnHandleRunException) then begin
  360. FOnHandleRunException(Self, AException, Result);
  361. end;
  362. end;
  363. procedure TIdThreadComponent.DoStopped(AThread: TIdThread);
  364. begin
  365. if Assigned(FOnStopped) then begin
  366. FOnStopped(Self);
  367. end;
  368. end;
  369. procedure TIdThreadComponent.DoTerminate;
  370. begin
  371. if Assigned(FOnTerminate) then begin
  372. FOnTerminate(Self);
  373. end;
  374. end;
  375. {$IFDEF USE_OBJECT_ARC}
  376. function TIdThreadComponent.GetDataObject: TObject;
  377. begin
  378. Result := FThread.DataObject;
  379. end;
  380. function TIdThreadComponent.GetDataValue: PtrInt;
  381. begin
  382. Result := FThread.DataValue;
  383. end;
  384. {$ELSE}
  385. function TIdThreadComponent.GetData: TObject;
  386. begin
  387. Result := FThread.Data;
  388. end;
  389. {$ENDIF}
  390. function TIdThreadComponent.GetHandle: TIdThreadHandle;
  391. begin
  392. Result := GetThreadHandle(FThread);
  393. end;
  394. function TIdThreadComponent.GetReturnValue: Integer;
  395. begin
  396. Result := FThread.ReturnValue;
  397. end;
  398. function TIdThreadComponent.GetStopMode: TIdThreadStopMode;
  399. begin
  400. if Assigned(FThread) then begin
  401. Result := FThread.StopMode;
  402. end else begin
  403. Result := FStopMode;
  404. end;
  405. end;
  406. function TIdThreadComponent.GetStopped: Boolean;
  407. begin
  408. if Assigned(FThread) then begin
  409. Result := FThread.Stopped;
  410. end else begin
  411. Result := True;
  412. end;
  413. end;
  414. function TIdThreadComponent.GetSuspended: Boolean;
  415. begin
  416. Result := FThread.Suspended;
  417. end;
  418. function TIdThreadComponent.GetTerminated: Boolean;
  419. begin
  420. if Assigned(FThread) then begin
  421. Result := FThread.Terminated;
  422. end else begin
  423. Result := True;
  424. end;
  425. end;
  426. function TIdThreadComponent.GetTerminatingException: string;
  427. begin
  428. Result := FThread.TerminatingException;
  429. end;
  430. function TIdThreadComponent.GetTerminatingExceptionClass: TClass;
  431. begin
  432. Result := FThread.TerminatingExceptionClass;
  433. end;
  434. procedure TIdThreadComponent.Loaded;
  435. begin
  436. inherited Loaded;
  437. // Active = True must not be performed before all other props are loaded
  438. if Assigned(FThread) and Assigned(OnTerminate) then begin
  439. FThread.OnTerminate := DoTerminate;
  440. end;
  441. if FActive then begin
  442. // Retoggle for load since we ignore during loading until all properties
  443. // are ready
  444. FActive := False;
  445. Active := True;
  446. end;
  447. end;
  448. procedure TIdThreadComponent.DoRun;
  449. begin
  450. if Assigned(FOnRun) then begin
  451. FOnRun(Self);
  452. end;
  453. end;
  454. procedure TIdThreadComponent.SetActive(const AValue: Boolean);
  455. begin
  456. if IsDesignTime or IsLoading then begin
  457. FActive := AValue;
  458. end
  459. else if Active <> AValue then begin
  460. if AValue then begin
  461. Start;
  462. end else begin
  463. Stop;
  464. end;
  465. FActive := AValue;
  466. end;
  467. end;
  468. {$IFDEF USE_OBJECT_ARC}
  469. procedure TIdThreadComponent.SetDataObject(const AValue: TObject);
  470. begin
  471. // this should not be accessed at design-time.
  472. FThread.DataObject := AValue;
  473. end;
  474. procedure TIdThreadComponent.SetDataValue(const AValue: PtrInt);
  475. begin
  476. // this should not be accessed at design-time.
  477. FThread.DataValue := AValue;
  478. end;
  479. {$ELSE}
  480. procedure TIdThreadComponent.SetData(const AValue: TObject);
  481. begin
  482. // this should not be accessed at design-time.
  483. FThread.Data := AValue;
  484. end;
  485. {$ENDIF}
  486. procedure TIdThreadComponent.SetReturnValue(const AValue: Integer);
  487. begin
  488. // this should not be accessed at design-time.
  489. FThread.ReturnValue := AValue;
  490. end;
  491. procedure TIdThreadComponent.SetStopMode(const AValue: TIdThreadStopMode);
  492. begin
  493. if Assigned(FThread) and not FThread.Terminated then begin
  494. FThread.StopMode := AValue;
  495. end;
  496. FStopMode := AValue;
  497. end;
  498. procedure TIdThreadComponent.Start;
  499. begin
  500. if not IsDesignTime then begin
  501. if Assigned(FThread) and FThread.Terminated then begin
  502. IdDisposeAndNil(FThread);
  503. end;
  504. if not Assigned(FThread) then begin
  505. FThread := TIdThreadEx.Create(Self);
  506. end;
  507. // MUST read from F variants as thread is now created
  508. if Assigned(FOnTerminate) then begin
  509. FThread.OnTerminate := DoTerminate;
  510. end else begin
  511. FThread.OnTerminate := nil;
  512. end;
  513. FThread.Name := FThreadName;
  514. FThread.Loop := FLoop;
  515. FThread.Priority := FPriority;
  516. FThread.StopMode := FStopMode;
  517. FThread.Start;
  518. end;
  519. end;
  520. procedure TIdThreadComponent.Stop;
  521. begin
  522. if Assigned(FThread) then begin
  523. FThread.Stop;
  524. end;
  525. end;
  526. procedure TIdThreadComponent.Synchronize(AMethod: TThreadMethod);
  527. begin
  528. FThread.Synchronize(AMethod);
  529. end;
  530. procedure TIdThreadComponent.Terminate;
  531. begin
  532. FThread.Terminate;
  533. end;
  534. procedure TIdThreadComponent.TerminateAndWaitFor;
  535. begin
  536. FThread.TerminateAndWaitFor;
  537. end;
  538. function TIdThreadComponent.WaitFor: UInt32;
  539. begin
  540. Result := FThread.WaitFor;
  541. end;
  542. function TIdThreadComponent.GetPriority: TIdThreadPriority;
  543. begin
  544. if Assigned(FThread) then begin
  545. Result := FThread.Priority;
  546. end else begin
  547. Result := FPriority;
  548. end;
  549. end;
  550. procedure TIdThreadComponent.SetPriority(const AValue: TIdThreadPriority);
  551. begin
  552. if Assigned(FThread) then begin
  553. if not FThread.Terminated then begin
  554. FThread.Priority := AValue;
  555. end;
  556. end;
  557. FPriority := AValue;
  558. end;
  559. function TIdThreadComponent.GetActive: Boolean;
  560. begin
  561. if IsDesignTime then begin
  562. Result := FActive;
  563. end else begin
  564. Result := IsRunning;
  565. end;
  566. end;
  567. procedure TIdThreadComponent.SetOnTerminate(const AValue: TIdNotifyThreadComponentEvent);
  568. begin
  569. FOnTerminate := AValue;
  570. if Assigned(FThread) then begin
  571. if Assigned(AValue) then begin
  572. FThread.OnTerminate := DoTerminate;
  573. end else begin
  574. FThread.OnTerminate := nil;
  575. end;
  576. end;
  577. end;
  578. procedure TIdThreadComponent.SetLoop(const AValue: Boolean);
  579. begin
  580. if IsRunning then begin
  581. raise EIdException.Create(RSThreadComponentLoopAlreadyRunning); // TODO: create a new Exception class for this
  582. end;
  583. FLoop := AValue;
  584. end;
  585. procedure TIdThreadComponent.SetThreadName(const AValue: string);
  586. begin
  587. if IsRunning then begin
  588. raise EIdException.Create(RSThreadComponentThreadNameAlreadyRunning); // TODO: create a new Exception class for this
  589. end;
  590. FThreadName := AValue;
  591. end;
  592. function TIdThreadComponent.IsRunning: Boolean;
  593. begin
  594. if Assigned(FThread) then begin
  595. Result := not FThread.Stopped;
  596. end else begin
  597. Result := False;
  598. end;
  599. end;
  600. procedure TIdThreadComponent.InitComponent;
  601. begin
  602. inherited InitComponent;
  603. StopMode := IdThreadComponentDefaultStopMode;
  604. Priority := IdThreadComponentDefaultPriority;
  605. end;
  606. end.