Jump to content
gioma

Custom Component : onDestroy delphi creates endless error messages

Recommended Posts

I created two visual components, one referencing the other in the published properties.

Example:

TComponentA = class(TComponent, IComponentAl)
	[weak] _ComponentB: TComponentB;
    //...other code
 private 
 	procedure SetCopmponentB ( const Value: TComponentB);
    //.. other code
 published 
 	property ComponentB: TComponentB read _ComponentB write SetCopmponentB;

//.. other code

procedure TComponentA.SetCopmponentB(const Value: TComponentB);
begin
  try
    _ComponentB := Value;
    //.. other code
  except
    on e:exception do
      WriteLog('[TComponentA.SetCopmponentB] EX: ' + e.Message);
  end;
end;

 

in the design phase, I add the two components ComponentA: TComponentA and ComponentB: TComponentB in the form.
By Deisngh i set the property ComponentA.ComponentB: = ComponentB.

Then if I delete ComponentA from design I have no problems, if instead I delete componentB (which is associated with the property of componentA) then Delphi goes into an exception unended loop.
What should I add to the code to prevent this from happening?

 

Share this post


Link to post
  1. Don't insert tabs in your source.
  2. Don't use [weak]
  3. Use the notification mechanism built into TComponent:
type
  TComponentA = class(TComponent, IComponentAl)
  private
    FComponentB: TComponentB;
  private 
    procedure SetComponentB(const Value: TComponentB);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  published 
    property ComponentB: TComponentB read FComponentB write SetComponentB;
  end;

procedure TComponentA.SetComponentB(const Value: TComponentB);
begin
  if (FComponentB <> nil) then
    FComponentB.RemoveFreeNotification(Self);
  FComponentB := Value;
  if (FComponentB <> nil) then
    FComponentB.AddFreeNotification(Self);
end;

procedure TComponentA.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if (AComponent = FComponentB) and (Operation = opRemove) then
    FComponentB := nil;
end;

 

  • Like 5

Share this post


Link to post

Thanks a lot, now I try.
But it's amazing that Delphi becomes impossible to close for this reason.
The error message loop is endless!

 

image.thumb.png.bb6b3f9321e7cc75ff4ceea1ab69bbf5.png

Share this post


Link to post

So evidently there's another problem with your code.

 

You can start by showing us the call stack (click the Details button).

Share this post


Link to post
9 hours ago, gioma said:

Thanks a lot, now I try.
But it's amazing that Delphi becomes impossible to close for this reason.
The error message loop is endless!

Did you make sure the rest of TComponentA's code is checking FComponentB for nil before accessing its members? It is hard to diagnose your problem without a complete example.

Share this post


Link to post
On 7/11/2022 at 3:41 PM, Anders Melander said:
  1. Don't insert tabs in your source.
  2. Don't use [weak]
  3. Use the notification mechanism built into TComponent:

type
  TComponentA = class(TComponent, IComponentAl)
  private
    FComponentB: TComponentB;
  private 
    procedure SetComponentB(const Value: TComponentB);
  protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  published 
    property ComponentB: TComponentB read FComponentB write SetComponentB;
  end;

procedure TComponentA.SetComponentB(const Value: TComponentB);
begin
  if (FComponentB <> nil) then
    FComponentB.RemoveFreeNotification(Self);
  FComponentB := Value;
  if (FComponentB <> nil) then
    FComponentB.AddFreeNotification(Self);
end;

procedure TComponentA.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if (AComponent = FComponentB) and (Operation = opRemove) then
    FComponentB := nil;
end;

 

I need the weak parameter, because in real use they are two components that refer to each other.

 

I solved it using the notification mechanism .

 

Thank you!

Share this post


Link to post
36 minutes ago, gioma said:

I need the weak parameter, because in real use they are two components that refer to each other.

No you don't. I understand why you used it but there are always better ways to solve a problem than using [weak].

 

Contrary to what the documentation states [weak] isn't named named after the type of reference. It's named after the design skills of people who choose to use it to manage references. 🙂

  • Like 1
  • Haha 3

Share this post


Link to post
48 minutes ago, gioma said:

I need the weak parameter, because in real use they are two components that refer to each other.

Weak attribute only works on interface references, not on object references. In your case, with TComponent reference, compiler just ignores weak attribute. 

  • Like 1

Share this post


Link to post
3 minutes ago, Anders Melander said:

No you don't. I understand why you used it but there are always better ways to solve a problem than using [weak].

 

Contrary to what the documentation states [weak] isn't named named after the type of reference. It's named after the design skills of people who choose to use it to manage references. 🙂

Weak references are integral part of ARC as memory management system. Because ARC was not main memory management system in classic compiler and was just an "add on", most code didn't require them or could use pointers that are equivalent of unsafe attribute.  Support for weak references in classic compiler was added only after they were added on mobile ARC compiler which requires weak references in order to have functional memory management system.

 

Proper coding pattern for ARC memory management would indeed require using weak attribute in the similar circumstances (code) OP had. In other words, if we would rewrite RTL and VCL to follow ARC rules then the OP original code would be the correct one, and we would not need nor have TComponent notification system.

  • Like 1

Share this post


Link to post
19 minutes ago, Anders Melander said:

No you don't. I understand why you used it but there are always better ways to solve a problem than using [weak].

 

Contrary to what the documentation states [weak] isn't named named after the type of reference. It's named after the design skills of people who choose to use it to manage references. 🙂

 

16 minutes ago, Dalija Prasnikar said:

Weak attribute only works on interface references, not on object references. In your case, with TComponent reference, compiler just ignores weak attribute. 

Right, you are right!
I have used weak on other occasions with Interfaces, in this case it is a TObject so it makes no sense to use it.
Distraction error 
Thanks again!

Share this post


Link to post

 

The shocking thing though is that if you make a mistake in creating a component and then install it, Delphi goes into an unending error loop and you are forced to close it from the task manager!

 

The IDE is still not very stable, although it costs a lot and its competitors are free!

 

I have been using Delphi for 16 years (Delphi 5, 7, delphi 2005 .. up to Delphi 11 Alexandria), in the beginning it was much better than Visual Studio .. now it is far behind and the updates are very, very, very slow to come out .. Visual studio has updates every week!

And I repeat .. Visual Studio is free!

Share this post


Link to post

sorry for the outburst, but sometimes it's really frustrating to work with Delphi .. you waste a lot of time with nonsense!

Share this post


Link to post
2 hours ago, gioma said:

The shocking thing though is that if you make a mistake in creating a component and then install it, Delphi goes into an unending error loop and you are forced to close it from the task manager!

Not very shocking if you understood what was going on. When you install a component your code will be run as a part of the IDE process. If your component code goes into an endless loop then you will have hung the IDE. Nothing surprising there.

 

 

2 hours ago, gioma said:

And I repeat .. Visual Studio is free!

So is Delphi. I'm assuming you're a hobbyist because otherwise VS isn't free AFAIK.

Share this post


Link to post

I think you would benefit from taking a break and acquiring some Delphi custom component development and debugging skills. Impatience to do something when you have not yet acquired the necessary skills and knowledge usually leads to frustration. The basics of component development and debugging have not changed much so even older books/guides are still useful.  Ray Konopka wrote some early books on Delphi component development any which would be a good resource if you can get your hands on one. 

  • Like 1

Share this post


Link to post
Posted (edited)
On 7/15/2022 at 3:16 PM, Anders Melander said:

Not very shocking if you understood what was going on. When you install a component your code will be run as a part of the IDE process. If your component code goes into an endless loop then you will have hung the IDE. Nothing surprising there.

 

 

So is Delphi. I'm assuming you're a hobbyist because otherwise VS isn't free AFAIK.

I was a hobbyist when I was 12 and I was programming in Basic with the Vic20.. 

Visual studio professional has a lower price base.

 

Yes, I understand that the error was caused by me, the IDE must rightly report it to me, but then it cannot go into an infinite loop of errors.

On 7/15/2022 at 3:29 PM, Brian Evans said:

I think you would benefit from taking a break and acquiring some Delphi custom component development and debugging skills. Impatience to do something when you have not yet acquired the necessary skills and knowledge usually leads to frustration. The basics of component development and debugging have not changed much so even older books/guides are still useful.  Ray Konopka wrote some early books on Delphi component development any which would be a good resource if you can get your hands on one

I have been developing with Delphi for many years (more than 16), but there are many aspects of programming and you never stop learning.
I don't often have to create a component, I usually buy them, use them and modify them if necessary.
In this case I had to make a component from 0, so I was faced with new problems for the first time.
I am not frustrated, but I expect that if I make a mistake I can analyze it, understand it and fix it.
If the IDE goes into an endless loop of errors I can't do anything anymore.

 

Sometimes for example it happens that when I update the component, if I go to recompile delphi it blocks the BPL file. The only way I have to re-install it is to close and reopen Delphi.

These are time wasters that you would not want to encounter when you have to develop in precise timing.

Edited by gioma

Share this post


Link to post

When you deverlop a custom component it is a good idea to use a test project first in which you create an instance of the component in code. This allows you to debug the run-time behaviour of the component without endangering the IDE itself. Only when everything works as it should do you add it to a design-time package and install it, to validate the design-time behaviour. If you need to add a custom property or class editor these can also be developed and tested in the test project, by just doing what the IDE designer does for invoking them. I don't remember the details since it has been literally decades since I last needed to do this, but it can be done.

  • Like 1

Share this post


Link to post
5 hours ago, PeterBelow said:

When you deverlop a custom component it is a good idea to use a test project first in which you create an instance of the component in code. This allows you to debug the run-time behaviour of the component without endangering the IDE itself. Only when everything works as it should do you add it to a design-time package and install it, to validate the design-time behaviour. If you need to add a custom property or class editor these can also be developed and tested in the test project, by just doing what the IDE designer does for invoking them. I don't remember the details since it has been literally decades since I last needed to do this, but it can be done.

It's a great idea, I did a similar thing, but the IDE got stuck anyway.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×