3

Is it safe to override Free method? I'm asking because I would like to use something like this. I know it's very ugly to use TerminateThread, but in my case it's very critical to kill the process with all its threads immediately.

I've seen the __free method declared in System.pas, but I don't know if it has something to do with the TObject.Free method and that's the reason why I'm asking if it's safe.

type
  TMyThread = class(TThread)
  private
    destructor Destroy; override;
  public
    procedure Execute; override;
    constructor Create;
    procedure Free(const Force: Boolean = False); // is it safe to use this?
  end;

procedure TMyThread.Free(const Force: Boolean = False);
begin
  if not Force then
  begin
    Terminate;
    WaitFor;
  end
  else
    TerminateThread(Handle, 0);

  inherited Free;
end;

destructor TMyThread.Destroy;
begin
  // free resources etc.
  inherited Destroy;
end;

Thank you

TLama
  • 141
  • 6
  • 1
    Your design seems wrong to me. And calling TerminateThread is just bad. Expect faults that are very intermittent and impossible to debug. Expect them to occur for your most critical clients!! – David Heffernan Sep 21 '11 at 11:50
  • @DavidHeffernan, agree but I'm working with blocking WinSock sockets and there's a problem. I need to shutdown the application immediately at the very special case and only when the [connect](http://msdn.microsoft.com/en-us/library/ms737625%28v=VS.85%29.aspx) API function is in progress. This function's timeout is about 20 seconds and this settings comes from the system configuration. I see that I can get unexpected behavior, but we already have a large system based on the blocking sockets and it's really needed to shut the thread immediately down. – TLama Sep 21 '11 at 12:00
  • 2
    `connect()` can be aborted by simply closing the socket from a different thread context. – Remy Lebeau Sep 22 '11 at 00:12

1 Answers1

10

You can't override Free because it's not virtual. If you define your own Free method it will hide the TObject.Free method (note the compiler warning) if the static type is your class type. This is definitely not a good idea since the object will then never get destroyed.

I don't see any reason why you want to do that. If you really want to use TerminateThread then just give your thread class another method ForceTerminate, in which you call TerminateThread.

jpfollenius
  • 16,456
  • 10
  • 90
  • 156
  • Thanks for the explanation. I was thinking about something like `ForceTerminate`. Anyway is it true that `the object will then never get destroyed`? If I call `inherited Free;` then it will or am I wrong? – TLama Sep 21 '11 at 09:00
  • @michael85 - you're welcome. As far as I understand it, `inherited` only works if you use overriding, which you don't. – jpfollenius Sep 21 '11 at 09:16
  • `inherited` is calling the ancestor's method apart from the fact that it's not overriden so I really get into the `TMyThread.Destroy;` method by calling `inherited Free;`. And you're right of course about the `override`, it was a typo. With my settings I can't even compile it because of error message `E2170 Cannot override a non-virtual method` I'm focusing rather on the fact if it's safe from System.pas point of view. – TLama Sep 21 '11 at 09:42
  • Well the "override" even made it in the title of your question, so I guess you're best off assking a separate question. The answer to your question as it stands is: `Free` cannot be overriden (safely or not). – jpfollenius Sep 21 '11 at 10:08
  • you're right `override` collides with the keyword. Maybe I should ask `Is it possible to create my own Free method` but it doesn't hit the exact meaning. Actually I want to override or overlap it in the human meaning, but well I'll accept your answer. – TLama Sep 21 '11 at 10:34
  • Still I think it is safe to `overlap` or `create` my own Free method because the `inherited` can continue with the ancestor's method chain. I won't to waste the SO database for asking another question, so sorry for confusing and thanks for the effort. – TLama Sep 21 '11 at 10:44
  • @michael85 Keep in mind that your `Free` method is only called if the static type is correct. If you access your thread as a `TObject`, `TThread` or any other base class, `TObject.Free` will be called without first calling your own method. – jpfollenius Sep 21 '11 at 11:34
  • that's right. Luckily this class won't have any descendants and even if yes, the Free method will have the Force parameter set to False by default. – TLama Sep 21 '11 at 11:43
  • @michael85: calling `TerminateThread()` will merely terminate and destroy the underlying Win32 API thread object that `TThread` wraps. You can still free the `TThread` object afterwards using the standard `Free()` method. – Remy Lebeau Sep 22 '11 at 00:14