Browse Source

Merge branch 'develop'

Unknown 6 years ago
parent
commit
c4e505b218

+ 184 - 28
Quick.Threads.pas

@@ -142,21 +142,38 @@ type
   TProc = procedure of object;
   {$ENDIF}
 
+  TAdvThread = class(TThread)
+  private
+    fExecuteProc : TProc;
+    fTerminateProc : TProc;
+    fExecuteWithSync : Boolean;
+    fTerminateWithSync : Boolean;
+    procedure DoExecute;
+    procedure CallToTerminate;
+  protected
+    procedure DoTerminate; override;
+  public
+    constructor Create(aProc : TProc; aSynchronize : Boolean);
+    procedure OnTerminate(aProc : TProc; aSynchronize : Boolean);
+    procedure Execute; override;
+  end;
+
   IAnonymousThread = interface
     procedure Start;
     function OnTerminate(aProc : TProc) : IAnonymousThread;
+    function OnTerminate_Sync(aProc : TProc) : IAnonymousThread;
   end;
 
   TAnonymousThread = class(TInterfacedObject,IAnonymousThread)
   private
-    fThread : TThread;
-    fTerminateProc : TProc;
-    constructor Create(aProc : TProc);
-    procedure NotifyTerminate(Sender : TObject);
+    fThread : TAdvThread;
+    constructor Create(aProc : TProc; aSynchronize : Boolean);
   public
-    class function Execute(aProc : TProc) : IAnonymousThread;
+    class function Execute(aProc : TProc) : IAnonymousThread; overload;
+    class function Execute_Sync(aProc : TProc) : IAnonymousThread; overload;
     procedure Start;
-    function OnTerminate(aProc : TProc) : IAnonymousThread;
+    function OnTerminate(aProc : TProc) : IAnonymousThread; overload;
+    function OnTerminate_Sync(aProc : TProc) : IAnonymousThread; overload;
   end;
 
   TParamArray = array of TFlexValue;
@@ -201,8 +218,11 @@ type
   IScheduledTask = interface(ITask)
   ['{AE551638-ECDE-4F64-89BF-F07BFCB9C9F7}']
     function OnException(aTaskProc : TTaskExceptionProc) : IScheduledTask;
+    function OnException_Sync(aTaskProc : TTaskExceptionProc) : IScheduledTask;
     function OnTerminated(aTaskProc : TTaskProc) : IScheduledTask;
+    function OnTerminated_Sync(aTaskProc : TTaskProc) : IScheduledTask;
     function OnExpired(aTaskProc : TTaskProc) : IScheduledTask;
+    function OnExpired_Sync(aTaskProc : TTaskProc) : IScheduledTask;
     function CheckSchedule : Boolean;
     procedure DoExpire;
     function GetTaskName : string;
@@ -228,6 +248,9 @@ type
     fTaskStatus : TWorkTaskStatus;
     fOwnedParams : Boolean;
     fEnabled : Boolean;
+    fExecuteWithSync : Boolean;
+    fExceptionWithSync : Boolean;
+    fTerminateWithSync : Boolean;
     function GetParam(aIndex : Integer) : TFlexValue;
     procedure DoExecute;
     procedure DoException(aException : Exception);
@@ -236,6 +259,10 @@ type
     procedure SetNumWorker(Value : Integer);
     function GetIdTask : Int64;
     procedure SetIdTask(Value : Int64);
+  protected
+    property ExecuteWithSync : Boolean read fExecuteWithSync write fExecuteWithSync;
+    property TerminateWithSync : Boolean read fTerminateWithSync write fTerminateWithSync;
+    property ExceptionWithSync : Boolean read fExceptionWithSync write fExceptionWithSync;
   public
     constructor Create(aParamArray : array of const; aOwnedParams : Boolean; aTaskProc : TTaskProc); virtual;
     destructor Destroy; override;
@@ -267,15 +294,21 @@ type
     fExpirationDate : TDateTime;
     fExpirationTimes : Integer;
     fFinished : Boolean;
+    fExpireWithSync: Boolean;
     procedure ClearSchedule;
     function CheckSchedule : Boolean;
     procedure DoExpire;
     function GetTaskName : string;
+  protected
+    property ExpireWithSync : Boolean read fExpireWithSync write fExpireWithSync;
   public
     property Name : string read fName write fName;
     function OnException(aTaskProc : TTaskExceptionProc) : IScheduledTask; virtual;
+    function OnException_Sync(aTaskProc : TTaskExceptionProc) : IScheduledTask; virtual;
     function OnTerminated(aTaskProc : TTaskProc) : IScheduledTask; virtual;
+    function OnTerminated_Sync(aTaskProc : TTaskProc) : IScheduledTask; virtual;
     function OnExpired(aTaskProc : TTaskProc) : IScheduledTask; virtual;
+    function OnExpired_Sync(aTaskProc : TTaskProc) : IScheduledTask; virtual;
     function StartAt(aStartDate : TDateTime) : IScheduledTask;
     procedure RunOnce;
     procedure RepeatEvery(aInterval : Integer; aTimeMeasure : TTimeMeasure); overload;
@@ -291,9 +324,12 @@ type
   private
     fNumWorker : Integer;
     fCurrentIdTask : Integer;
-    fCurrentTask : IWorkTask;
     fStatus : TWorkerStatus;
     fTaskQueue : TTaskQueue;
+    procedure ExecuteTask;
+    procedure TerminateTask;
+  protected
+    fCurrentTask : ITask;
   public
     constructor Create(aNumWorker : Integer; aTaskQueue : TTaskQueue);
     property NumWorker : Integer read fNumWorker;
@@ -303,7 +339,7 @@ type
 
   TScheduledWorker = class(TWorker)
   private
-    fTask : IScheduledTask;
+    procedure ExpireTask;
   public
     constructor Create(aNumWorker : Integer; aScheduledTask: IScheduledTask);
     procedure Execute; override;
@@ -331,7 +367,9 @@ type
     property NumPushedTasks : Int64 read fNumPushedTasks;
     property ConcurrentWorkers : Integer read fConcurrentWorkers write fConcurrentWorkers;
     function AddTask(aTaskProc : TTaskProc) : IWorkTask; overload;
+    function AddTask_Sync(aTaskProc : TTaskProc) : IWorkTask; overload;
     function AddTask(aParamArray : array of const; aOwnedParams : Boolean; aTaskProc : TTaskProc) : IWorkTask; overload;
+    function AddTask_Sync(aParamArray : array of const; aOwnedParams : Boolean; aTaskProc : TTaskProc) : IWorkTask; overload;
     procedure Start;
     procedure CancelAll;
   end;
@@ -344,6 +382,7 @@ type
     fCondVar : TSimpleEvent;
     fTaskList : TScheduledTaskList;
     fRemoveTaskAfterExpiration : Boolean;
+    procedure ExpireTask;
   public
     constructor Create(aTaskList : TScheduledTaskList);
     destructor Destroy; override;
@@ -368,7 +407,9 @@ type
     property RemoveTaskAfterExpiration : Boolean read fRemoveTaskAfterExpiration write fRemoveTaskAfterExpiration;
     property IsStarted : Boolean read fIsStarted;
     function AddTask(const aTaskName : string; aTaskProc : TTaskProc) : IScheduledTask; overload;
+    function AddTask_Sync(const aTaskName : string; aTaskProc : TTaskProc) : IScheduledTask; overload;
     function AddTask(const aTaskName : string; aParamArray : array of const; aOwnedParams : Boolean; aTaskProc : TTaskProc) : IScheduledTask; overload;
+    function AddTask_Sync(const aTaskName : string; aParamArray : array of const; aOwnedParams : Boolean; aTaskProc : TTaskProc) : IScheduledTask; overload;
     function GetTask(aIdTask : Int64) : IScheduledTask; overload;
     function GetTask(const aTaskName : string) : IScheduledTask; overload;
     procedure Start;
@@ -837,30 +878,31 @@ end;
 
 { TAnonymousThread }
 
-constructor TAnonymousThread.Create(aProc : TProc);
+constructor TAnonymousThread.Create(aProc : TProc; aSynchronize : Boolean);
 begin
-  {$IFNDEF FPC}
-  fThread := TThread.CreateAnonymousThread(aProc);
-  {$ELSE}
-  fThread := TThread.CreateAnonymousThread(@aProc);
-  {$ENDIF}
+  fThread := TAdvThread.Create(aProc,aSynchronize);
 end;
 
 class function TAnonymousThread.Execute(aProc: TProc): IAnonymousThread;
 begin
-  Result := TAnonymousThread.Create(aProc);
+  Result := TAnonymousThread.Create(aProc,False);
 end;
 
-procedure TAnonymousThread.NotifyTerminate(Sender: TObject);
+class function TAnonymousThread.Execute_Sync(aProc: TProc): IAnonymousThread;
 begin
-  fTerminateProc;
+  Result := TAnonymousThread.Create(aProc,True);
 end;
 
 function TAnonymousThread.OnTerminate(aProc: TProc): IAnonymousThread;
 begin
   Result := Self;
-  fTerminateProc := aProc;
-  fThread.OnTerminate := Self.NotifyTerminate;
+  fThread.OnTerminate(aProc,False);
+end;
+
+function TAnonymousThread.OnTerminate_Sync(aProc: TProc): IAnonymousThread;
+begin
+  Result := Self;
+  fThread.OnTerminate(aProc,True);
 end;
 
 procedure TAnonymousThread.Start;
@@ -875,6 +917,9 @@ var
   i : Integer;
 begin
   fTaskStatus := TWorkTaskStatus.wtsPending;
+  fExecuteWithSync := False;
+  fTerminateWithSync := False;
+  fExceptionWithSync := False;
   fOwnedParams := aOwnedParams;
   SetLength(fParamArray,High(aParamArray)+1);
   for i := Low(aParamArray) to High(aParamArray) do
@@ -1028,6 +1073,17 @@ begin
   end;
 end;
 
+function TBackgroundTasks.AddTask_Sync(aParamArray: array of const; aOwnedParams: Boolean; aTaskProc: TTaskProc): IWorkTask;
+begin
+  Result := AddTask(aParamArray,aOwnedParams,aTaskProc);
+  TTask(Result).ExecuteWithSync := True;
+end;
+
+function TBackgroundTasks.AddTask_Sync(aTaskProc: TTaskProc): IWorkTask;
+begin
+  Result := AddTask_Sync([],False,aTaskProc);
+end;
+
 procedure TBackgroundTasks.Start;
 var
   i : Integer;
@@ -1055,6 +1111,16 @@ begin
   FreeOnTerminate := False;
 end;
 
+procedure TWorker.ExecuteTask;
+begin
+  fCurrentTask.DoExecute;
+end;
+
+procedure TWorker.TerminateTask;
+begin
+  fCurrentTask.DoTerminate;
+end;
+
 procedure TWorker.Execute;
 begin
   fStatus := TWorkerStatus.wsIdle;
@@ -1066,7 +1132,8 @@ begin
       fStatus := TWorkerStatus.wsWorking;
       try
         fCurrentIdTask := fCurrentTask.GetIdTask;
-        fCurrentTask.DoExecute;
+        if TTask(fCurrentTask).ExecuteWithSync then Synchronize(ExecuteTask)
+          else fCurrentTask.DoExecute;
       except
         on E : Exception do
         begin
@@ -1075,7 +1142,8 @@ begin
         end;
       end;
     finally
-      fCurrentTask.DoTerminate;
+      if TTask(fCurrentTask).TerminateWithSync then Synchronize(TerminateTask)
+        else fCurrentTask.DoTerminate;
       fStatus := TWorkerStatus.wsIdle;
     end;
   end;
@@ -1101,6 +1169,17 @@ begin
   Result := scheduletask;
 end;
 
+function TScheduledTasks.AddTask_Sync(const aTaskName: string; aParamArray: array of const; aOwnedParams: Boolean; aTaskProc: TTaskProc): IScheduledTask;
+begin
+  Result := AddTask(aTaskName,aParamArray,aOwnedParams,aTaskProc);
+  TTask(Result).ExecuteWithSync := True;
+end;
+
+function TScheduledTasks.AddTask_Sync(const aTaskName: string; aTaskProc: TTaskProc): IScheduledTask;
+begin
+  Result := AddTask_Sync(aTaskName,aTaskProc);
+end;
+
 constructor TScheduledTasks.Create;
 begin
   fNumPushedTasks := 0;
@@ -1284,52 +1363,84 @@ begin
   Result := Self;
 end;
 
+function TScheduledTask.OnException_Sync(aTaskProc: TTaskExceptionProc): IScheduledTask;
+begin
+  Result := OnException(aTaskProc);
+  TTask(Result).ExceptionWithSync := True;
+end;
+
 function TScheduledTask.OnExpired(aTaskProc: TTaskProc): IScheduledTask;
 begin
   fExpiredProc := aTaskProc;
   Result := Self;
 end;
 
+function TScheduledTask.OnExpired_Sync(aTaskProc: TTaskProc): IScheduledTask;
+begin
+  Result := OnExpired(aTaskProc);
+  TScheduledTask(Result).ExpireWithSync := True;
+end;
+
 function TScheduledTask.OnTerminated(aTaskProc: TTaskProc): IScheduledTask;
 begin
   fTerminateProc := aTaskProc;
   Result := Self;
 end;
 
+function TScheduledTask.OnTerminated_Sync(aTaskProc: TTaskProc): IScheduledTask;
+begin
+  Result := OnTerminated(aTaskProc);
+  TTask(Result).TerminateWithSync := True;
+end;
+
 { TScheduledWorker }
 
 constructor TScheduledWorker.Create(aNumWorker : Integer; aScheduledTask: IScheduledTask);
 begin
   inherited Create(aNumWorker,nil);
+  NameThreadForDebugging(aScheduledTask.Name,aScheduledTask.IdTask);
   FreeOnTerminate := True;
-  fTask := aScheduledTask;
+  fCurrentTask := aScheduledTask;
 end;
 
 procedure TScheduledWorker.Execute;
 begin
   fStatus := TWorkerStatus.wsIdle;
-  if Assigned(fTask) then
+  if Assigned(fCurrentTask) then
   begin
     try
       fStatus := TWorkerStatus.wsWorking;
       try
-        fTask.DoExecute;
+        if TTask(fCurrentTask).ExecuteWithSync then Synchronize(ExecuteTask)
+          else fCurrentTask.DoExecute;
         fStatus := TWorkerStatus.wsIdle;
       except
         on E : Exception do
         begin
-          if fTask <> nil then fTask.DoException(E)
+          if fCurrentTask <> nil then fCurrentTask.DoException(E)
             else raise Exception.Create(e.Message);
         end;
       end;
     finally
-      fTask.DoTerminate;
+      if TTask(fCurrentTask).TerminateWithSync then Synchronize(TerminateTask)
+        else fCurrentTask.DoTerminate;
+      //check if expired
+      if (fCurrentTask as IScheduledTask).IsFinished then
+      begin
+        if TScheduledTask(fCurrentTask).ExpireWithSync then Synchronize(ExpireTask)
+          else (fCurrentTask as IScheduledTask).DoExpire;
+      end;
     end;
   end;
-  fTask := nil;
+  fCurrentTask := nil;
   fStatus := TWorkerStatus.wsSuspended;
 end;
 
+procedure TScheduledWorker.ExpireTask;
+begin
+  (fCurrentTask as IScheduledTask).DoExpire;
+end;
+
 { TScheduler }
 
 constructor TScheduler.Create(aTaskList : TScheduledTaskList);
@@ -1381,7 +1492,8 @@ begin
         begin
           if task.IsEnabled then
           begin
-            task.DoExpire;
+            //if TScheduledTask(task).ExpireWithSync then Synchronize(ExpireTask)
+            //  else task.DoExpire;
             if fRemoveTaskAfterExpiration then fTaskList.Remove(task);
           end;
         end;
@@ -1394,6 +1506,11 @@ begin
   end;
 end;
 
+procedure TScheduler.ExpireTask;
+begin
+
+end;
+
 function TScheduler.Add(aTask: TScheduledTask): Integer;
 begin
   Result := fTaskList.Add(aTask);
@@ -1429,4 +1546,43 @@ begin
   end;
 end;
 
+{ TAdvThread }
+
+constructor TAdvThread.Create(aProc : TProc; aSynchronize : Boolean);
+begin
+  inherited Create(True);
+  FreeOnTerminate := True;
+  fExecuteWithSync := aSynchronize;
+  fExecuteProc := aProc;
+end;
+
+procedure TAdvThread.DoExecute;
+begin
+  if Assigned(fExecuteProc) then fExecuteProc;
+end;
+
+procedure TAdvThread.CallToTerminate;
+begin
+  if Assigned(fTerminateProc) then fTerminateProc;
+end;
+
+procedure TAdvThread.DoTerminate;
+begin
+  if fTerminateWithSync then Synchronize(CallToTerminate)
+    else CallToTerminate;
+end;
+
+procedure TAdvThread.Execute;
+begin
+  if fExecuteWithSync then Synchronize(DoExecute)
+    else DoExecute;
+end;
+
+
+procedure TAdvThread.OnTerminate(aProc: TProc; aSynchronize: Boolean);
+begin
+  fTerminateWithSync := aSynchronize;
+  fTerminateProc := aProc;
+end;
+
 end.

+ 8 - 2
Quick.Value.pas

@@ -7,7 +7,7 @@
   Author      : Kike Pérez
   Version     : 1.4
   Created     : 07/01/2019
-  Modified    : 15/01/2019
+  Modified    : 16/01/2019
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -176,7 +176,11 @@ type
 
   TFlexValue = record
   private
+    {$IFNDEF FPC}
     fDataIntf : IInterface;
+    {$ELSE}
+    fDataIntf : TValueData;
+    {$ENDIF}
     fDataType : TValueDataType;
     function CastToString : string;
     {$IFNDEF NEXTGEN}
@@ -533,7 +537,9 @@ begin
     vtPointer : AsPointer := Value.VPointer;
     else raise Exception.Create('DataType not supported by TFlexValue');
   end;
-  //fDataIntf._AddRef;
+  {$IFDEF FPC}
+  fDataIntf._AddRef;
+  {$ENDIF}
 end;
 
 {$IFNDEF FPC}

+ 23 - 4
README.md

@@ -251,7 +251,12 @@ SMTP.SendMail;
 - **TThreadedQueueCS:** Version of TThreadedQueue with Critical Section.
 - **TThreadObjectList:** Thread safe Object List.
 - **TThreadedQueueList:** Thread safe Queue List. Autogrow and with Critical Section.
-- **TAnonymousThread:** Creates anonymous thread defining unchained Execute and OnTerminate methods.
+- **TAnonymousThread:** Creates anonymous thread defining unchained Execute and OnTerminate methods. Use Execute_Sync and OnTerminate_Sync methods if code needs to update UI.
+  - *Execute:* Specify code to execute on start.
+  - *Execute_Sync:* Like Execute but runs code with syncronized thread method (avoids problems if your code updates UI).
+  - *OnTerminate:* Specify code to execute when task finishes.
+  - *OnTerminate_Sync:* Like OnTerminate but runs code with syncronized thread method (avoids problems if your code updates UI).
+  - *Start:* Starts thread execution.
 ```delphi
 //simple anonymousthread
 TAnonymousThread.Execute(
@@ -270,7 +275,13 @@ TAnonymousThread.Execute(
       end)
     .Start;
 ```
-- **TBackgroundsTasks:** Launch tasks in background allowing number of concurrent workers.
+- **TBackgroundsTasks:** Launch tasks in background allowing number of concurrent workers. Use AddTask_Sync and OnTerminate_Sync methods if code needs to update UI.
+  - *AddTask:* Specify Task name, parameters to pass to anonymous method(If OwnedParams=true, task will free params on expiration task) and method than will be executed. 
+  - *AddTask_Sync:* Like AddTask but runs code with synchronize thread method (avoids problems if your code updates UI).
+  - *OnTerminate:* Specify code to execute when task finishes.
+  - *OnTerminate_Sync:* Like OnTerminate but runs code with syncronized thread method (avoids problems if your code updates UI).
+  - *OnException:* Specify code to execute when task generates an exception.
+  - *Start:* Starts tasks execution.
 ```delphi
     backgroundtasks := TBackgroundTasks.Create(10);
     for i := 1 to 100 do
@@ -299,12 +310,20 @@ TAnonymousThread.Execute(
     end;
     backgroundtasks.Start;
 ```
-- **TScheduledTasks:** Alternative to Timer. You can assign tasks with start time, repeat options and expiration date.
+- **TScheduledTasks:** Alternative to Timer. You can assign tasks with start time, repeat options and expiration date. Use AddTask_Sync, OnTerminate_Sync and OnExpired_Sync if code needs to update UI.
 You can assign anonymous methods to execute, exception, terminate and expiration events.
   - *AddTask:* Specify Task name, parameters to pass to anonymous method(If OwnedParams=true, task will free params on expiration task) and method than will be executed. 
+  - *AddTask_Sync:* Like AddTask but runs code with synchronize thread method (avoids problems if your code updates UI).
+  - *OnTerminate:* Specify code to execute when task finishes.
+  - *OnTerminate_Sync:* Like OnTerminate but runs code with syncronized thread method (avoids problems if your code updates UI).
+  - *OnExpire:* Specify code to execute when task expiration reached or task was cancelled.
+  - *OnExpire_Sync:* Like OnExpire but runs code with synchronized thread method (avoids problems if your code updates UI).
+  - *OnException:* Specify code to execute when task generates an exception.
   - *StartAt:* Date and time to start task.
   - *RunOnce:* Task will executed only one time. If there aren't a previous StartAt, task will be executed immediately.
-  - *RepeatEvery:* Can indicate repeat step over time and expiration date. If not previous StartAtspecified, task will be executed immediately.
+  - *RepeatEvery:* Can indicate repeat step over time and expiration date. If not previous StartAt was specified, task will be executed immediately.
+  - *Start:* Starts scheduler.
+  - *Stop:* Stops scheduler.
 ```delphi
 myjob := TMyJob.Create;
 myjob.Name := Format('Run at %s and repeat every 1 second until %s',[DateTimeToStr(ScheduledDate),DateTimeToStr(ExpirationDate)]);

+ 14 - 43
samples/delphi/QuickThreads/AnonymousThread/AnonymousThread.dproj

@@ -160,13 +160,24 @@
                 </Source>
             </Delphi.Personality>
             <Deployment Version="3">
+                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
+                    <Platform Name="OSX32">
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
+                <DeployFile LocalName="Win32\Debug\AnonymousThread.exe" Configuration="Debug" Class="ProjectOutput">
+                    <Platform Name="Win32">
+                        <RemoteName>AnonymousThread.exe</RemoteName>
+                        <Overwrite>true</Overwrite>
+                    </Platform>
+                </DeployFile>
                 <DeployFile LocalName="$(BDS)\Redist\osx64\libcgsqlite3.dylib" Class="DependencyModule">
                     <Platform Name="OSX64">
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>
-                <DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
-                    <Platform Name="OSX32">
+                <DeployFile LocalName="$(BDS)\Redist\iossimulator\libPCRE.dylib" Class="DependencyModule">
+                    <Platform Name="iOSSimulator">
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>
@@ -185,12 +196,6 @@
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>
-                <DeployFile LocalName="Win32\Debug\AnonymousThread.exe" Configuration="Debug" Class="ProjectOutput">
-                    <Platform Name="Win32">
-                        <RemoteName>AnonymousThread.exe</RemoteName>
-                        <Overwrite>true</Overwrite>
-                    </Platform>
-                </DeployFile>
                 <DeployClass Name="AdditionalDebugSymbols">
                     <Platform Name="iOSSimulator">
                         <Operation>1</Operation>
@@ -200,6 +205,7 @@
                         <Operation>1</Operation>
                     </Platform>
                     <Platform Name="Win32">
+                        <RemoteDir>Contents\MacOS</RemoteDir>
                         <Operation>0</Operation>
                     </Platform>
                 </DeployClass>
@@ -335,11 +341,6 @@
                         <Operation>1</Operation>
                         <Extensions>.framework</Extensions>
                     </Platform>
-                    <Platform Name="OSX64">
-                        <RemoteDir>Contents\MacOS</RemoteDir>
-                        <Operation>1</Operation>
-                        <Extensions>.framework</Extensions>
-                    </Platform>
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                     </Platform>
@@ -362,11 +363,6 @@
                         <Operation>1</Operation>
                         <Extensions>.dylib</Extensions>
                     </Platform>
-                    <Platform Name="OSX64">
-                        <RemoteDir>Contents\MacOS</RemoteDir>
-                        <Operation>1</Operation>
-                        <Extensions>.dylib</Extensions>
-                    </Platform>
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                         <Extensions>.dll;.bpl</Extensions>
@@ -390,11 +386,6 @@
                         <Operation>1</Operation>
                         <Extensions>.dylib</Extensions>
                     </Platform>
-                    <Platform Name="OSX64">
-                        <RemoteDir>Contents\MacOS</RemoteDir>
-                        <Operation>1</Operation>
-                        <Extensions>.dylib</Extensions>
-                    </Platform>
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                         <Extensions>.bpl</Extensions>
@@ -417,10 +408,6 @@
                         <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
                         <Operation>0</Operation>
                     </Platform>
-                    <Platform Name="OSX64">
-                        <RemoteDir>Contents\Resources\StartUp\</RemoteDir>
-                        <Operation>0</Operation>
-                    </Platform>
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                     </Platform>
@@ -568,30 +555,18 @@
                         <RemoteDir>..\</RemoteDir>
                         <Operation>1</Operation>
                     </Platform>
-                    <Platform Name="OSX64">
-                        <RemoteDir>..\</RemoteDir>
-                        <Operation>1</Operation>
-                    </Platform>
                 </DeployClass>
                 <DeployClass Name="ProjectOSXInfoPList">
                     <Platform Name="OSX32">
                         <RemoteDir>Contents</RemoteDir>
                         <Operation>1</Operation>
                     </Platform>
-                    <Platform Name="OSX64">
-                        <RemoteDir>Contents</RemoteDir>
-                        <Operation>1</Operation>
-                    </Platform>
                 </DeployClass>
                 <DeployClass Name="ProjectOSXResource">
                     <Platform Name="OSX32">
                         <RemoteDir>Contents\Resources</RemoteDir>
                         <Operation>1</Operation>
                     </Platform>
-                    <Platform Name="OSX64">
-                        <RemoteDir>Contents\Resources</RemoteDir>
-                        <Operation>1</Operation>
-                    </Platform>
                 </DeployClass>
                 <DeployClass Required="true" Name="ProjectOutput">
                     <Platform Name="Android">
@@ -614,10 +589,6 @@
                         <RemoteDir>Contents\MacOS</RemoteDir>
                         <Operation>1</Operation>
                     </Platform>
-                    <Platform Name="OSX64">
-                        <RemoteDir>Contents\MacOS</RemoteDir>
-                        <Operation>1</Operation>
-                    </Platform>
                     <Platform Name="Win32">
                         <Operation>0</Operation>
                     </Platform>

+ 6 - 6
samples/firemonkey/QuickThreads/ScheduledTasks/RunScheduledTasks.dproj

@@ -382,21 +382,21 @@
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>
-                <DeployFile LocalName="Android\Debug\libRunScheduledTasks.so" Configuration="Debug" Class="ProjectOutput">
+                <DeployFile LocalName="$(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png" Configuration="Debug" Class="Android_SplashImage426">
                     <Platform Name="Android">
-                        <RemoteName>libRunScheduledTasks.so</RemoteName>
+                        <RemoteName>splash_image.png</RemoteName>
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>
-                <DeployFile LocalName="$(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png" Configuration="Debug" Class="Android_LauncherIcon144">
+                <DeployFile LocalName="Android\Debug\libRunScheduledTasks.so" Configuration="Debug" Class="ProjectOutput">
                     <Platform Name="Android">
-                        <RemoteName>ic_launcher.png</RemoteName>
+                        <RemoteName>libRunScheduledTasks.so</RemoteName>
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>
-                <DeployFile LocalName="$(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png" Configuration="Debug" Class="Android_SplashImage426">
+                <DeployFile LocalName="$(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png" Configuration="Debug" Class="Android_LauncherIcon144">
                     <Platform Name="Android">
-                        <RemoteName>splash_image.png</RemoteName>
+                        <RemoteName>ic_launcher.png</RemoteName>
                         <Overwrite>true</Overwrite>
                     </Platform>
                 </DeployFile>

BIN
samples/firemonkey/QuickThreads/ScheduledTasks/RunScheduledTasks.res


+ 9 - 9
samples/firemonkey/QuickThreads/ScheduledTasks/main.pas

@@ -89,7 +89,7 @@ begin
   myjob := TMyJob.Create;
     myjob.Id := 1;
     myjob.Name := 'Run now and repeat every 1 second for 5 times';
-    scheduledtasks.AddTask('Task1',[myjob,1],True,
+    scheduledtasks.AddTask_Sync('Task1',[myjob,1],True,
                             procedure(task : ITask)
                             begin
                               Log('task "%s" started',[TMyJob(task.Param[0]).Name]);
@@ -100,12 +100,12 @@ begin
                             begin
                               Log('task "%s" failed (%s)',[TMyJob(task.Param[0]).Name,aException.Message]);
                             end
-                          ).OnTerminated(
+                          ).OnTerminated_Sync(
                             procedure(task : ITask)
                             begin
                               Log('task "%s" finished',[TMyJob(task.Param[0]).Name]);
                             end
-                          ).OnExpired(
+                          ).OnExpired_Sync(
                             procedure(task : ITask)
                             begin
                               Log('task "%s" expired',[TMyJob(task.Param[0]).Name]);
@@ -115,7 +115,7 @@ begin
     myjob := TMyJob.Create;
     myjob.Id := 2;
     myjob.Name := 'Run now, repeat every 1 second forever';
-    scheduledtasks.AddTask('Task2',[myjob,32,true,3.2,myjob.ClassType],True,
+    scheduledtasks.AddTask_Sync('Task2',[myjob,32,true,3.2,myjob.ClassType],True,
                             procedure(task : ITask)
                             begin
                               Log('task "%s" started with params(Int=%d / Bool=%s / Float=%s /Class=%s)',[TMyJob(task.Param[0]).Name,task.Param[1].AsInteger,task.Param[2].AsString,task.Param[3].AsString,task.Param[4].AsString]);
@@ -126,12 +126,12 @@ begin
                             begin
                               Log('task "%s" failed (%s)',[TMyJob(task.Param[0]).Name,aException.Message]);
                             end
-                          ).OnTerminated(
+                          ).OnTerminated_Sync(
                             procedure(task : ITask)
                             begin
                               Log('task "%s" finished',[TMyJob(task.Param[0]).Name]);
                             end
-                          ).OnExpired(
+                          ).OnExpired_Sync(
                             procedure(task : ITask)
                             begin
                               Log('task "%s" expired',[TMyJob(task.Param[0]).Name]);
@@ -147,7 +147,7 @@ begin
     myjob.Name := Format('Run at %s and repeat every 1 second until %s',[DateTimeToStr(ScheduledDate),DateTimeToStr(ExpirationDate)]);
 
 
-    scheduledtasks.AddTask('Task3',[myjob],True,
+    scheduledtasks.AddTask_Sync('Task3',[myjob],True,
                             procedure(task : ITask)
                             begin
                               Log('task "%s" started',[TMyJob(task.Param[0]).Name]);
@@ -158,12 +158,12 @@ begin
                             begin
                               Log('task "%s" failed (%s)',[TMyJob(task.Param[0]).Name,aException.Message]);
                             end
-                          ).OnTerminated(
+                          ).OnTerminated_Sync(
                             procedure(task : ITask)
                             begin
                               Log('task "%s" finished',[TMyJob(task.Param[0]).Name]);
                             end
-                          ).OnExpired(
+                          ).OnExpired_Sync(
                             procedure(task : ITask)
                             begin
                               Log('task "%s" expired',[TMyJob(task.Param[0]).Name]);

+ 1 - 1
samples/fpc/QuickThreads/ScheduledTasks/RunScheduledTasks.lpr

@@ -37,7 +37,7 @@ procedure TMyJob.DoJob(task : ITask);
 var
   a, b, i : Integer;
 begin
-  cout('[%s] task "%s" doing a %s job...',[DateTimeToStr(Now()),fName,task.Param[0].AsString],etInfo);
+  cout('[%s] task "%s" doing a %s job %d...',[DateTimeToStr(Now()),fName,task.Param[0].AsString,task.Param[1].AsInteger],etInfo);
   Sleep(Random(1000));
   a := Random(100);
   b := Random(5) + 1;