创建线程以访问另一个类';程序和变量 我一直使用C++,我不擅长德尔菲(XE)。但出于原因,我必须将我的C++代码移植到Delphi来实现以下任务。我有一个主TForm,我从其他人那里获得了代码。在TForm中,我定义了两个私有对象和过程来完成一些任务。我的任务是创建一个线程来调用这些类和过程进行一些计算 TASKForm = class(TForm) private MonitorA :TMonClassA; ConstB :TConstClassB; procedure calculateStmp; end; P>如果多继承继承任务形式,则可以在C++中轻松完成。但经过一些研究,我发现德尔福并不支持这一点。所以我需要另想办法。然后我看到了一篇关于使用嵌套类的文章 TASKForm = class(TForm) protected TMyThread = class(TThread) public procedure Execute(); override; // inside this I need to call TASKForm.MonitorA.somemethod, TASKForm.ConstB.somemethod and TASKForm.calculateStmp end private MonitorA :TMonClassA; ConstB :TConstClassB; procedure calculateStmp; end;
但是我很快发现嵌套类中定义的过程无法访问容器的私有成员。我想知道是否有其他方法可以创建一个线程来调用一个类的私有函数和变量?谢谢创建线程以访问另一个类';程序和变量 我一直使用C++,我不擅长德尔菲(XE)。但出于原因,我必须将我的C++代码移植到Delphi来实现以下任务。我有一个主TForm,我从其他人那里获得了代码。在TForm中,我定义了两个私有对象和过程来完成一些任务。我的任务是创建一个线程来调用这些类和过程进行一些计算 TASKForm = class(TForm) private MonitorA :TMonClassA; ConstB :TConstClassB; procedure calculateStmp; end; P>如果多继承继承任务形式,则可以在C++中轻松完成。但经过一些研究,我发现德尔福并不支持这一点。所以我需要另想办法。然后我看到了一篇关于使用嵌套类的文章 TASKForm = class(TForm) protected TMyThread = class(TThread) public procedure Execute(); override; // inside this I need to call TASKForm.MonitorA.somemethod, TASKForm.ConstB.somemethod and TASKForm.calculateStmp end private MonitorA :TMonClassA; ConstB :TConstClassB; procedure calculateStmp; end;,delphi,delphi-xe,Delphi,Delphi Xe,但是我很快发现嵌套类中定义的过程无法访问容器的私有成员。我想知道是否有其他方法可以创建一个线程来调用一个类的私有函数和变量?谢谢 代码已更新。我正在尝试另外两个方案。第一种是使用像 TmyThread = interface(TThread) end; TASKForm = class(TForm, TmyThread) private MonitorA :TMonClassA; ConstB :TConstClassB; procedure calculateStmp; en
代码已更新。我正在尝试另外两个方案。第一种是使用像
TmyThread = interface(TThread)
end;
TASKForm = class(TForm, TmyThread)
private
MonitorA :TMonClassA;
ConstB :TConstClassB;
procedure calculateStmp;
end;
但它不起作用,因为TThread不是一种接口类型。我正在尝试使用Application.ProcessMessages,如下所示
procedure TASKForm.RunMyTask;
while (not RunTerminated) do // RunTerminated will be set when an external event triggered
begin
MonitorA.Somemethod;
calculateStmp;
ConstB.Somemethod;
Application.ProcessMessages;
end;
end
我会说这个方法是“ok”,但不是完美的,因为MonitorA.Somemethod和ConstB.Somemethod可能需要很长或很短的时间来运行(时间不是常数),所以有时候当外部事件触发将RunTerminated设置为True时,它不会立即终止while循环。我仍然在寻找多线程的方法 根据David Heffernan的评论进行编辑。
第一步。使用回调过程创建TThread的子代-如下所示
type
TOnMyExecute = procedure( Sender : TObject ) of object; // sender not required here but is convention
TMyThread = class( TThread )
private
fMyOnExecute : TOnMyExecute;
public
procedure Execute(); override; // inside this I need to call TASKForm.MonitorA.somemethod, TASKForm.ConstB.somemethod and TASKForm.calculateStmp
property MyOnExecute : TMyOnExecute read fMyOnExecute write fMyOnExecute;
end;
TMyThread.OnExecute;
begin
if assigned( fMyOnExecute ) then
begin
fMyOnExecute( self );
end;
end;
第2步与以前一样创建TForm的后代
TASKForm = class(TForm)
protected
MyThread : TMyThread;
private
MonitorA :TMonClassA;
ConstB :TConstClassB;
procedure calculateStmp;
procedure MyPrivateActions( Sender : TObject );
end;
在某个地方,可能在TaskForm.Create中,或者在线程启动时,将MyPrivateActions分配给MyTask.MyOnExecute
MyTask.MyOnExecute := MyPrivateActions;
最后,TMyThread OnExecute看起来是这样的
type
TOnMyExecute = procedure( Sender : TObject ) of object; // sender not required here but is convention
TMyThread = class( TThread )
private
fMyOnExecute : TOnMyExecute;
public
procedure Execute(); override; // inside this I need to call TASKForm.MonitorA.somemethod, TASKForm.ConstB.somemethod and TASKForm.calculateStmp
property MyOnExecute : TMyOnExecute read fMyOnExecute write fMyOnExecute;
end;
TMyThread.OnExecute;
begin
if assigned( fMyOnExecute ) then
begin
fMyOnExecute( self );
end;
end;
关键是,尽管线程正在执行函数,但函数属于窗体,窗体可以访问它自己的私有成员。Delphi支持多重继承,但只有在使用接口时才支持。一个Delphi类只能有一个具体的基类,但可以实现多个接口。因此,您可以定义一个接口来访问您的成员。或者,您可以简单地将它们作为参数传递给thread类的构造函数。谢谢Remy。我尝试了代码(刚刚添加),但它说TThread不是一种接口类型,因此我无法将接口添加到我的表单类中。我的代码中是否缺少任何东西。
TThread
是一个具体的类,而不是一个接口。不能从TForm
和TThread
继承TASKForm
。我先前建议的要点是为您定义一个自定义的接口
,它为您的私有成员公开访问器,然后TASKForm
可以实现这些访问器。然后将TASKForm
的接口传递给线程,这样它就可以在需要时访问成员。但是如果TASKForm
和线程定义在同一个单元中,这就太过分了。线程将有权访问TASKForm
的私有成员(Delphi在单元中使用隐式友谊),因此您真正需要做的就是将TASKForm
对象指针传递给线程,然后它可以直接访问表单对象的成员。您不想这样做。您希望将数据移出表单并移动到thread类中。在表单中具有线程访问状态是一种可怕的代码气味。TThead确实用于该问题。当然,您的代码使用TTask
。它来自线程库。这是XE没有的。线程库是在XE7中引入的。即使如此,TTask
也不应该被子类化。而且,我认为它没有虚拟的Execute
方法。您的意思是TThread
而不是TTask
?您的thread子类的问题是它必须暂停启动。您应该删除MyOnExecute
属性,而是在构造函数中提供该信息。是的,必须将其启动挂起或作为创建过程的一部分提供回调。如果您建议将MonitorA和ConstB作为参数传递给构造函数,当然这是可能的,但是TAskForm随后会失去对变量的控制,这对我来说会破坏私有变量的对象。否。TOnMyExecute
应该传递给线程的构造函数。这样您就不会强迫消费者创建暂停。此时属性是无意义的,应该删除。无论如何,一个更大的问题是询问者的整个设计和方法都是错误的。