Advertisement
Guest User

Untitled

a guest
Feb 24th, 2015
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.83 KB | None | 0 0
  1. unit ThreadingEx;
  2.  
  3. interface
  4.  
  5. uses
  6. SysUtils,
  7. Threading;
  8.  
  9. type
  10. TAction<T> = reference to procedure(const arg: T);
  11. TAction2<T> = reference to procedure(const taskStatus:TTaskStatus; const arg: T);
  12.  
  13. TTaskContinuationOptions = (
  14. NotOnCompleted,
  15. NotOnFaulted,
  16. NotOnCanceled,
  17. OnlyOnCompleted,
  18. OnlyOnFaulted,
  19. OnlyOnCanceled
  20. );
  21.  
  22. TTaskContinuationOptionsSet = set of TTaskContinuationOptions;
  23.  
  24. ITaskEx = interface(ITask)
  25. ['{3AE1A614-27AA-4B5A-BC50-42483650E20D}']
  26. function GetExceptObj: Exception;
  27. function GetStatus: TTaskStatus;
  28. function ContinueWith(const continuationAction: TAction<ITaskEx>;
  29. continuationOptions: TTaskContinuationOptions): ITaskEx;
  30. function ContinueWithGui(const continuationAction: TAction<ITaskEx>;
  31. continuationOptions: TTaskContinuationOptions): ITaskEx;
  32. function ContinueWithGui2(continuationOptions: TTaskContinuationOptionsSet;
  33. const continuationAction: TAction2<ITaskEx>): ITaskEx;
  34. property ExceptObj: Exception read GetExceptObj;
  35. property Status: TTaskStatus read GetStatus;
  36. end;
  37.  
  38. TTaskEx = class(TTask, ITaskEx)
  39. private
  40. fExceptObj: Exception;
  41. function GetExceptObj: Exception;
  42. function InternalContinueWith(const continuationAction: TAction<ITaskEx>;
  43. continuationOptions: TTaskContinuationOptions;
  44. invokeInMainThread: Boolean): ITaskEx;
  45. function InternalContinueWith2(continuationOptions: TTaskContinuationOptionsSet; const continuationAction: TAction2<ITaskEx>;
  46. invokeInMainThread: Boolean): ITaskEx;
  47.  
  48. protected
  49. function ContinueWith(const continuationAction: TAction<ITaskEx>;
  50. continuationOptions: TTaskContinuationOptions): ITaskEx;
  51. function ContinueWithGui(const continuationAction: TAction<ITaskEx>;
  52. continuationOptions: TTaskContinuationOptions): ITaskEx;
  53. function ContinueWithGui2(continuationOptions: TTaskContinuationOptionsSet;
  54. const continuationAction: TAction2<ITaskEx>): ITaskEx;
  55. public
  56. destructor Destroy; override;
  57. class function Run(const action: TProc): ITaskEx; static;
  58. end;
  59.  
  60. implementation
  61.  
  62. uses
  63. Classes;
  64.  
  65. { TTaskEx }
  66.  
  67. function TTaskEx.ContinueWith(const continuationAction: TAction<ITaskEx>;
  68. continuationOptions: TTaskContinuationOptions): ITaskEx;
  69. begin
  70. Result := InternalContinueWith(continuationAction, continuationOptions, False);
  71. end;
  72.  
  73. function TTaskEx.ContinueWithGui(const continuationAction: TAction<ITaskEx>;
  74. continuationOptions: TTaskContinuationOptions): ITaskEx;
  75. begin
  76. Result := InternalContinueWith(continuationAction, continuationOptions, True);
  77. end;
  78.  
  79. function TTaskEx.ContinueWithGui2(
  80. continuationOptions: TTaskContinuationOptionsSet;
  81. const continuationAction: TAction2<ITaskEx>): ITaskEx;
  82. begin
  83. Result := InternalContinueWith2(continuationOptions, continuationAction, True);
  84. end;
  85.  
  86. destructor TTaskEx.Destroy;
  87. begin
  88. fExceptObj.Free;
  89. inherited;
  90. end;
  91.  
  92. function TTaskEx.GetExceptObj: Exception;
  93. begin
  94. if (fExceptObj is EAggregateException)
  95. and (EAggregateException(fExceptObj).Count = 1) then
  96. Result := EAggregateException(fExceptObj)[0]
  97. else
  98. Result := fExceptObj;
  99. end;
  100.  
  101. function TTaskEx.InternalContinueWith(
  102. const continuationAction: TAction<ITaskEx>;
  103. continuationOptions: TTaskContinuationOptions;
  104. invokeInMainThread: Boolean): ITaskEx;
  105. begin
  106. Result := TTaskEx.Run(
  107. procedure
  108. var
  109. task: ITaskEx;
  110. doContinue: Boolean;
  111. begin
  112. task := Self;
  113. if not IsComplete then
  114. DoneEvent.WaitFor;
  115. fExceptObj := GetExceptionObject;
  116. case continuationOptions of
  117. NotOnCompleted: doContinue := GetStatus <> TTaskStatus.Completed;
  118. NotOnFaulted: doContinue := GetStatus <> TTaskStatus.Exception;
  119. NotOnCanceled: doContinue := GetStatus <> TTaskStatus.Canceled;
  120. OnlyOnCompleted: doContinue := GetStatus = TTaskStatus.Completed;
  121. OnlyOnFaulted: doContinue := GetStatus = TTaskStatus.Exception;
  122. OnlyOnCanceled: doContinue := GetStatus = TTaskStatus.Canceled;
  123. else
  124. doContinue := False;
  125. end;
  126. if doContinue then
  127. if invokeInMainThread then
  128. TThread.Queue(nil,
  129. procedure
  130. begin
  131. continuationAction(task);
  132. end)
  133. else
  134. continuationAction(task);
  135. end);
  136. end;
  137.  
  138. function TTaskEx.InternalContinueWith2(
  139. continuationOptions: TTaskContinuationOptionsSet;
  140. const continuationAction: TAction2<ITaskEx>;
  141. invokeInMainThread: Boolean): ITaskEx;
  142. begin
  143. Result := TTaskEx.Run(
  144. procedure
  145. var
  146. task: ITaskEx;
  147. doContinue: Boolean;
  148. begin
  149. task := Self;
  150. if not IsComplete then
  151. DoneEvent.WaitFor;
  152. fExceptObj := GetExceptionObject;
  153. doContinue := ((NotOnCompleted in continuationOptions) and (GetStatus <> TTaskStatus.Completed)) or
  154. ((NotOnFaulted in continuationOptions) and (GetStatus <> TTaskStatus.Exception)) or
  155. ((NotOnCanceled in continuationOptions) and (GetStatus <> TTaskStatus.Canceled)) or
  156. ((OnlyOnCompleted in continuationOptions) and (GetStatus = TTaskStatus.Completed)) or
  157. ((OnlyOnFaulted in continuationOptions) and (GetStatus = TTaskStatus.Exception)) or
  158. ((OnlyOnCanceled in continuationOptions) and (GetStatus = TTaskStatus.Canceled));
  159. if doContinue then
  160. if invokeInMainThread then
  161. TThread.Queue(nil,
  162. procedure
  163. begin
  164. continuationAction(GetStatus, task);
  165. end)
  166. else
  167. continuationAction(GetStatus, task);
  168. end);
  169. end;
  170.  
  171. class function TTaskEx.Run(const action: TProc): ITaskEx;
  172. var
  173. task: TTaskEx;
  174. begin
  175. task := TTaskEx.Create(nil, TNotifyEvent(nil), action, TThreadPool.Default, nil);
  176. Result := task.Start as ITaskEx;
  177. end;
  178.  
  179.  
  180. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement