Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
创建线程以访问另一个类';程序和变量 我一直使用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 - Fatal编程技术网

创建线程以访问另一个类';程序和变量 我一直使用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
应该传递给线程的构造函数。这样您就不会强迫消费者创建暂停。此时属性是无意义的,应该删除。无论如何,一个更大的问题是询问者的整个设计和方法都是错误的。