A task is created using the CreateTask function, which takes as a parameter a global procedure, a method, an instance of the TOmniWorker class (or, usually, a descendant of that class) or an anonymous procedure (in Delphi 2009 and newer). CreateTask will also accept an optional second parameter, a task name, which will be displayed in the Delphi’s Thread view on the thread running the task.
type TOmniTaskProcedure = procedure(const task: IOmniTask); TOmniTaskMethod = procedure(const task: IOmniTask) of object; TOmniTaskDelegate = reference to procedure(const task: IOmniTask); function CreateTask(worker: TOmniTaskProcedure; const taskName: string = ''): IOmniTaskControl; overload; function CreateTask(worker: TOmniTaskMethod; const taskName: string = ''): IOmniTaskControl; overload; function CreateTask(worker: TOmniTaskDelegate; const taskName: string = ''): IOmniTaskControl; overload; function CreateTask(const worker: IOmniWorker; const taskName: string = ''): IOmniTaskControl; overload;CreateTask returns a feature-full interface IOmniTaskControl which we will explore in this chapter. The most important function in this interface, Run, will create a new thread and start your task in it.
Low-level For the Impatient
The following code represents the simplest possible low-level OmniThreadLibrary example. It executes the Beep function in a background thread. The Beep function merely beeps and exits. By exiting from the task function, the Windows thread running the task is also terminated.
procedure TfrmTestSimple.Beep(const task: IOmniTask); begin //Executed in a background thread MessageBeep(MB_ICONEXCLAMATION); end; CreateTask(Beep, 'Beep').Run;Another way to start a task is to call a Schedule function which starts it in a thread allocated from a thread pool. This is covered in the Thread Pooling chapter.
Four ways to create a task
Let’s examine all four ways of creating a task. The simplest possible way (demoed in application 2_TwoWayHello) is to pass a name of a global procedure to the CreateTask. This global procedure must consume one parameter of type IOmniTask .
procedure RunHelloWorld(const task: IOmniTask); begin // end; CreateTask(RunHelloWorld, 'HelloWorld').Run;A variation on the theme is passing a name of a method to the CreateTask. This approach is used in the demo application 1_HelloWorld. The interesting point here is that you can declare this method in the same class from which the CreateTask is called. That way you can access all class fields and methods from the threaded code. Just keep in mind that you’ll be doing this from another thread so make sure you know what you’re doing!
procedure TfrmTestHelloWorld.RunHelloWorld(const task: IOmniTask); begin // end; procedure TfrmTestHelloWorld.StartTask; begin CreateTask(RunHelloWorld, 'HelloWorld').Run; end;In Delphi 2009 and newer you can also write the task code as an anonymous function.
CreateTask( procedure (const task: IOmniTask) begin // end, 'HellowWorld').Run;For all except the simplest tasks, you’ll use the fourth approach as it will give you access to the true OmniThreadLibrary power (namely internal wait loop and message dispatching). To use it, you have to create a worker object deriving from the TOmniWorker class.
type THelloWorker = class(TOmniWorker) end; procedure TfrmTestTwoWayHello.actStartHelloExecute(Sender: TObject); begin FHelloTask := CreateTask(THelloWorker.Create(), 'Hello'). Run; end;IOmniTaskControl and IOmniTask Interfaces
When you create a low-level task, OmniThreadLibrary returns a task controller interface IOmniTaskControl. This interface, which is defined in the OtlTaskControl unit, can be used to control the task from the owner’s side. The task code, on the other hand, has access to another interface, IOmniTask (defined in the OtlTask unit), which can be used to communicate with the owner and manipulate the task itself. A picture in the Tasks vs. Threads chapter shows the relationship between those interfaces.
This chapter deals mainly with these two interfaces. For the reference reasons, the IOmniTaskControl is reprinted here in full. In the rest of the chapter I’ll just show relevant interface parts.
The IOmniTask interface is described at the end of this chapter.
type IOmniTaskControl = interface function Alertable: IOmniTaskControl; function CancelWith(const token: IOmniCancellationToken): IOmniTaskControl; function ChainTo(const task: IOmniTaskControl; ignoreErrors: boolean = false): IOmniTaskControl; function ClearTimer(timerID: integer): IOmniTaskControl; function DetachException: Exception; function Enforced(forceExecution: boolean = true): IOmniTaskControl; function GetFatalException: Exception; function GetParam: TOmniValueContainer; function Invoke(const msgMethod: pointer): IOmniTaskControl; overload; function Invoke(const msgMethod: pointer; msgData: array of const): IOmniTaskControl; overload; function Invoke(const msgMethod: pointer; msgData: TOmniValue): IOmniTaskControl; overload; function Invoke(const msgName: string): IOmniTaskControl; overload; function Invoke(const msgName: string; msgData: array of const): IOmniTaskControl; overload; function Invoke(const msgName: string; msgData: TOmniValue): IOmniTaskControl; overload; function Invoke(remoteFunc: TOmniTaskControlInvokeFunction): IOmniTaskControl; overload; function Invoke(remoteFunc: TOmniTaskControlInvokeFunctionEx): IOmniTaskControl; overload; function Join(const group: IOmniTaskGroup): IOmniTaskControl; function Leave(const group: IOmniTaskGroup): IOmniTaskControl; function MonitorWith(const monitor: IOmniTaskControlMonitor): IOmniTaskControl; function MsgWait(wakeMask: DWORD = QS_ALLEVENTS): IOmniTaskControl; function OnMessage(eventDispatcher: TObject): IOmniTaskControl; overload; function OnMessage(eventHandler: TOmniTaskMessageEvent): IOmniTaskControl; overload; function OnMessage(msgID: word; eventHandler: TOmniTaskMessageEvent): IOmniTaskControl; overload; function OnMessage(msgID: word; eventHandler: TOmniMessageExec): IOmniTaskControl; overload; function OnMessage(eventHandler: TOmniOnMessageFunction): IOmniTaskControl; overload; function OnMessage(msgID: word; eventHandler: TOmniOnMessageFunction): IOmniTaskControl; overload; function OnTerminated(eventHandler: TOmniOnTerminatedFunction): IOmniTaskControl; overload; function OnTerminated(eventHandler: TOmniOnTerminatedFunctionSimple): IOmniTaskControl; overload; function OnTerminated(eventHandler: TOmniTaskTerminatedEvent): IOmniTaskControl; overload; function RemoveMonitor: IOmniTaskControl; function Run: IOmniTaskControl; function Schedule(const threadPool: IOmniThreadPool = nil {default pool}): IOmniTaskControl; function SetMonitor(hWindow: THandle): IOmniTaskControl; function SetParameter(const paramName: string; const paramValue: TOmniValue): IOmniTaskControl; overload; function SetParameter(const paramValue: TOmniValue): IOmniTaskControl; overload; function SetParameters(const parameters: array of TOmniValue): IOmniTaskControl; function SetPriority(threadPriority: TOTLThreadPriority): IOmniTaskControl; function SetQueueSize(numMessages: integer): IOmniTaskControl; function SetTimer(timerID: integer; interval_ms: cardinal; const timerMessage: TOmniMessageID): IOmniTaskControl; overload; function SetUserData(const idxData: TOmniValue; const value: TOmniValue): IOmniTaskControl; procedure Stop; function Terminate(maxWait_ms: cardinal = INFINITE): boolean; function TerminateWhen(event: THandle): IOmniTaskControl; overload; function TerminateWhen(token: IOmniCancellationToken): IOmniTaskControl; overload; function Unobserved: IOmniTaskControl; function WaitFor(maxWait_ms: cardinal): boolean; function WaitForInit: boolean; function WithCounter(const counter: IOmniCounter): IOmniTaskControl; function WithLock(const lock: TSynchroObject; autoDestroyLock: boolean = true): IOmniTaskControl; overload; function WithLock(const lock: IOmniCriticalSection): IOmniTaskControl; overload; property CancellationToken: IOmniCancellationToken read GetCancellationToken; property Comm: IOmniCommunicationEndpoint read GetComm; property ExitCode: integer read GetExitCode; property ExitMessage: string read GetExitMessage; property FatalException: Exception read GetFatalException; property Lock: TSynchroObject read GetLock; property Name: string read GetName; property Param: TOmniValueContainer read GetParam; property UniqueID: int64 read GetUniqueID; property UserData[const idxData: TOmniValue]: TOmniValue read GetUserDataVal write SetUserDataVal; end;
Copied from: https://leanpub.com/omnithreadlibrary
0 comments:
Post a Comment