问题描述
我想向ITask/TTask添加一些功能.我将新方法包装在继承自ITask的新接口(IMyTask)中:
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;
我的类包含应在其构造函数中初始化的成员(例如FSomeList).因此,调用我的构造函数是强制性的.同时,我不想更改Create()的实现.因此,我将Create()声明为具有四个覆盖的构造函数.但是创建TMyTask实例无法使用E2251进行编译:
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;
我尝试使用"Reintroduce"关键字,但似乎不起作用,可能是因为所有Create()方法都标记有"Overload".
I tried with "Reintroduce" keyword but it seems not to work may be because all Create() methods are marked with "Overload".
如何克服这个问题?
更新:
进一步的测试得出两个QC:
Further tests resulted in two QCs:
- QC129032: Using TTask.WaitForAll() causes a deadlock
- QC129032: ITask.Cancel does not process complete events
推荐答案
为什么要创建TTask后代?除非在极少数情况下,否则不应创建TTask后代.更好的解决方案是在另一个对象中使用常规任务.
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.
TTask上的Create方法实际上不是构造函数,而是静态类函数.这样做的原因是确保仅使用ITask而不直接使用TTask.您也不能使用默认的无参数构造函数构造TTask(它会引发异常).来源甚至在该构造函数附近有一条注释
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;
正如我所说,最好直接使用TTask的Create或Run方法而不创建后代.如果要封装任务的操作,请随时创建自己的类类型并在内部创建和计划任务.
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).
这篇关于XE7中的TTask的子类:E2251对“创建"的歧义重载调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!