有没有办法从一个线程(另一个类)访问我的组件事件(私有声明)?

时间:2016-01-02 10:53:30

标签: multithreading components private lazarus freepascal

我创建了一个组件,我在其中使用了线程,如下所示:

type
  TEvent = procedure(sender:TObject) of object;

  TMyComponent = class(TComponent)
  protected
    Fvar:String;
    FMyEvent:TEvent;
  public
    Constructor Create(AOwner:TComponent);override;
  published
    property MyProperty:String read Fvar write Fvar;
    property Event:TEvent read FMyEvent write FMyEvent;
  end;

  TMyThread = class(TThread)
    procedure Execute; override;
  end;

implementation

procedure TMyThread.Execute;
begin
  if assigned (FMyEvent) then
    FMyEvent(Self);
end;  

正如您所看到的,我从另一个类访问FMyEvent这是一个私有变量,所以这会产生一个编译错误(Undeclared Identifier),我知道它访问私有变量的不合逻辑从另一个班级,但我真的需要使用这个!我需要在执行TMyThread时发生该事件。 我试过这段代码:

  type
  TEvent = procedure(sender:TObject) of object;

  TMyComponent = class(TComponent)
  protected
  Fvar:String;
  FMyEvent:TEvent;
  public
  Constructor Create(AOwner:TComponent);override;
  published
  property MyProperty:String read Fvar write Fvar;
  property Event:TEvent read FMyEvent write FMyEvent;
  end;
  TMyThread = class(TThread)
  private 
  fev:TEvent;
  protected
  procedure Execute; override;
  public
  constructor   Create(afev:TEvent);
  end;

  implementation
  procedure TMyThread.Create(afev:TEvent);//when i call this one i send the real Event of the component.
  begin
  fev:=afev;
  if assigned (FMyEvent) then
   FMyEvent(Self);      // it works here
  end;

 procedure TMyThread.Execute;
 begin
 if assigned (FMyEvent) then
  FMyEvent(Self);      //IT doesn't work here
  end;  

正如你所看到的,当我创建线程时,我将组件的属性作为参数发送,我在两个不同的地方调用了事件,所以当我在构造函数中调用它时效果很好,但是当我调用它时执行程序没有任何反应!!但是条件:if assigned (FMyEvent)在两种情况下都是正确的(我尝试了一些测试来检查这个)。我想问题与" Self"我应该替换另一个所有者吗?为什么只有在创建过程中调用它时事件才有效?

1 个答案:

答案 0 :(得分:2)

  1. FMyEvent 不是私密的,受到保护。
  2. 它也发布为事件,因此可以访问。
  3. 您需要一个实例来访问已发布的活动。
  4. 错误未声明标识符实际上来自第3点,而不是来自可见性。

    它应该像

    procedure TMyThread.Execute;
    begin
      if assigned (Instance.Event) then
        Instance.Event(Self);
    end;
    

    或者您可以使用事件作为参数创建线程。

    TMyThread = class(TThread)
    private
      FMyEvent: TEvent;
    public
      constructor construct(ev: TEvent);
      procedure Execute; override;
    end; 
    
    constructor TMyThread.construct(ev: TEvent);
    begin
      FMyEvent := ev;
    end;
    
    procedure TMyThread.Execute;
    begin
      if assigned (FMyEvent) then
        FMyEvent(Self);
    end;