3

I am trying to compose my own ThreadManager unit in Delphi and I have this so far:

unit uThreadManager;

interface

uses
  Classes,
  Windows;

type
  TCustomTThread = class (TThread)
  public
    TaskData : Pointer;
end;

type
  TWorkerThread = class(TObject)
  private
    TaskDataList : TList;
    TaskDataListCrit : TRTLCriticalSection;
    function ReadTotalTasks : Integer;
  public
    constructor Create;
    destructor Destroy; override;
    property TotalTasks : Integer read ReadTotalTasks;
    function AddTask(Thread: TCustomTThread; Data: Pointer) : Integer;
    procedure Delete (Index : Integer);
end;

implementation

type
  PTaskData = ^TTaskData;
  TTaskData = record
  Thread          : TCustomTThread;
  TaskPointer     : Pointer;
end;

procedure TWorkerThread.Delete(Index: Integer);
var
  TaskData : PTaskData;
begin
  EnterCriticalSection(TaskDataListCrit);
  TaskData := TaskDataList.Items[Index];
  TaskDataList.Delete(Index);
  LeaveCriticalSection(TaskDataListCrit);
  TaskData^.Thread.Free;
  Dispose(TaskData);
end;

function TWorkerThread.ReadTotalTasks;
begin
  EnterCriticalSection(TaskDataListCrit);
  result := TaskDataList.Count;
  LeaveCriticalSection(TaskDataListCrit);
end;

destructor TWorkerThread.Destroy;
begin
  DeleteCriticalSection(TaskDataListCrit);
  TaskDataList.Free;
  inherited;
end;

constructor TWorkerThread.Create;
begin
  inherited;
  InitializeCriticalSection(TaskDataListCrit);
  TaskDataList    := TList.Create;
end;

function TWorkerThread.AddTask(Thread: TCustomTThread; Data: Pointer) : Integer;
var
  NewTask : PTaskData;
begin
  EnterCriticalSection(TaskDataListCrit);
  New(NewTask);
  // I would like to create a new instance of TCustomTThread here!
  //NewTask^.Thread       := ...
  NewTask^.TaskPointer  := Data;
  result                := TaskDataList.Add (NewTask);
  LeaveCriticalSection(TaskDataListCrit);
end;

end.

I came across the problem with the parameter from my AddTask procedure...

Here is an example on what I am trying to do:

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, uThreadManager;

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

type
  TTheCustomThread = class (TCustomTThread)
  public
    procedure Execute; override;
end;

implementation

{$R *.dfm}

procedure TTheCustomThread.Execute;
begin
 // My Code
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  NewWorkerThread : TWorkerThread;
begin
  NewWorkerThread := TWorkerThread.Create;
  NewWorkerThread.AddTask(TTheCustomThread, NIL);
end;

end.

this code gives me the error:

[dcc32 Error] Unit2.pas(42): E2010 Incompatible types: 'TCustomTThread' and 'class of TTheCustomThread'

I could fix this by declaring a new TTheCustomThread var in the stack but I would like to avoid this cause I won't need it at all later and AddTask will create a new instance of TTheCustomThread. I could use TClass and then typecast to TCustomThread but I was wondering if there's anything else to make this work.

Thank you for your help.

0

1 Answer 1

5

Your function AddTask is defined as so:

function AddTask(Thread: TCustomTThread; Data: Pointer) : Integer;  

The first parameter that you pass is of type TCustomTThread. That is an instance of TCustomTThread.

You call the function like this:

AddTask(TTheCustomThread, nil);

Here you pass the class rather than an instance. Hence the compiler error.

Now, it seems that what you want to do is pass the class. Inside AddTask you wish to receive a class and then create a new instance. Declare a class type like so:

type
  TTheCustomThreadClass = class of TTheCustomThread;

Change AddTask to receive that type:

function AddTask(ThreadClass: TCustomTThreadClass; Data: Pointer) : Integer;  

And inside the implementation, create an instance like this:

NewTask^.Thread := ThreadClass.Create;

Very likely you will want to declare the constructor of TTheCustomThread to be virtual to allow derived classes the freedom to define constructors that can be executed from your factory creation mechanism.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.