Sub classing TTask in XE7: E2251 Ambiguous overloaded call to 'Create'

我怕爱的太早我们不能终老 提交于 2019-12-24 18:11:22

问题


I want to add some functionality to ITask/TTask. I wrapped the new methods in a new Interface (IMyTask) which inherits from ITask:

type

  IMyTask = interface(ITask)
    procedure MyNewMethod;
  end;

  TMyTask = class(TTask, ITask, IMyTask)
    private
      FSomeList: TList<integer>;
    public
      procedure MyNewMethod;

      constructor Create(const AProc: TProc; AThreadPool: TThreadPool = nil); overload;
      constructor Create(Sender: TObject; Event: TNotifyEvent); overload;
      constructor Create(const Proc: TProc); overload;
      constructor Create(Sender: TObject; Event: TNotifyEvent; const APool: TThreadPool); overload;

  end;

My class contains members that should be initialized in its constructor (for example FSomeList). So calling my constructor is mandatory. In the same time I didn't want to change the implementation of Create(). So I re declared Create() as constructor with four overrides. But creating an instance of TMyTask fails to compile with E2251:

procedure TestCreateMyTask;
var
  i: IMyTask;
begin
  i := TMyTask.Create(  // --> E2251 Ambiguous overloaded call to 'Create'
    procedure
    begin
    end
  );
end;

I tried with "Reintroduce" keyword but it seems not to work may be because all Create() methods are marked with "Overload".

How to overcome this problem?

UPDATE:

Further tests resulted in two QCs:

  • QC129032: Using TTask.WaitForAll() causes a deadlock
  • QC129032: ITask.Cancel does not process complete events

回答1:


Why do you feel you should create a TTask descendant? You should not create a TTask descendant except in very rare circumstances. The better solution is to use a regular task within another object.

The Create methods on TTask aren't actually constructors, rather they're static class functions. The reason for this is to ensure that you only ever work with an ITask and not the TTask directly. You also cannot construct a TTask with the default parameter-less constructor (it raises an exception). The source even has a comment near that constructor

  constructor Create; overload; // do not call this constructor!!

The difference between the "Create" functions and the "Run" functions is whether or not the task is scheduled. Run will return a task already scheduled into the thread pool. Create will defer that to when the caller decides to schedule it.

  class function Create(Sender: TObject; Event: TNotifyEvent): ITask; overload; static; inline;
  class function Create(const Proc: TProc): ITask; overload; static; inline;
  class function Create(Sender: TObject; Event: TNotifyEvent; const APool: TThreadPool): ITask; overload; static; inline;
  class function Create(const Proc: TProc; APool: TThreadPool): ITask; overload; static; inline;
  class function Run(Sender: TObject; Event: TNotifyEvent): ITask; overload; static; inline;
  class function Run(Sender: TObject; Event: TNotifyEvent; APool: TThreadPool): ITask; overload; static; inline;
  class function Run(const Func: TProc): ITask; overload; static; inline;
  class function Run(const Func: TProc; APool: TThreadPool): ITask; overload; static; inline;

As I said, it is better to simply use the TTask Create or Run methods directly and not create a descendant. If you want to encapsulate the task's operations, feel free to create your own class type and internally create and schedule the task(s).



来源:https://stackoverflow.com/questions/27081623/sub-classing-ttask-in-xe7-e2251-ambiguous-overloaded-call-to-create

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!