1

I have a small Windows software created with Delphi 7 where a thread periodically do some action, like save information in a SQLite database. It works just fine, but the same thread never execute when Windows is about to shutdown/reboot/logoff. Here is a simple example:

type
  TSaveText = class(TThread)
  private
    FText: string;
  protected
    procedure Execute; override;
  end;

...

  private
    procedure WMQueryEndSession(var AMsg: TMessage); message WM_QUERYENDSESSION;
    procedure SaveText(const AText: string);

...

procedure AddToLog(const Str: string);
var
  Pth: string;
  Txt: TextFile;
begin
  Pth := ExtractFilePath(ParamStr(0)) + 'log.txt';
  try
    AssignFile(Txt, Pth);
    if not FileExists(Pth) then
      ReWrite(Txt);
    Append(Txt);
    WriteLn(Txt, Trim(Str));
  finally
    CloseFile(Txt);
  end;
end;

procedure TfrmMain.SaveText(const AText: String);
begin
  with TSaveText.Create(True) do
  begin
    FText := AText;
    FreeOnTerminate := True;
    Priority := tpNormal;
    Resume;
  end;
end;

procedure TSaveText.Execute;
begin
  inherited;
  AddToLog(FText);
end;

procedure TfrmMain.WMQueryEndSession(var AMsg: TMessage);
begin
  inherited;
  SaveText('Windows is about to shutdown/reboot/logoff!');
  AMsg.Result := 1;
end;

In this example, the text 'Windows is about to shutdown/reboot/logoff!' is never saved in the log file. But if I remove the action from the thread, it works:

procedure TfrmMain.WMQueryEndSession(var AMsg: TMessage);
begin
  inherited;
  AddToLog('Windows is about to shutdown/reboot/logoff!');
  AMsg.Result := 1;
end;

I'd like to know if there is a way to force thread to execute in this scenario, when Windows is about to shutdown/reboot/logoff.

Thanks!

Guybrush
  • 1,575
  • 2
  • 27
  • 51
  • 1
    The thread doesn't have its own message pump. It will never handle Windows messages, therefore events like the Windows shutdown (etc) will not be received or handled in your thread. Either rethink your design, or make sure that the thread have a standard Windows message pump. – Some programmer dude Mar 16 '18 at 01:49
  • As @Someprogrammerdude says, messages are sent to windows, not threads. If you want the thread to get them, you'll need to make sure it has a message pump (dispatcher) and use `AllocateHWND` to get a window handle that gets those messages. – Ken White Mar 16 '18 at 02:39
  • Thank you for the comments! It's almost 1 am in my local time, I will research about the pointed solution tomorrow morning and let you know. – Guybrush Mar 16 '18 at 03:15
  • 2
    @KenWhite except that `AllocateHWND` is not thread-safe. Better to have the thread call `CreateWindow/Ex` directly instead. Or have the main thread catch the message and delegate it to the worker thread for processing. Which is actually what the OP's code is trying to do. I see nothing wrong with the code itself, so the likely explanation is that the pending system shutdown is somehow interfering with the underlying worker thread being created or resumed, or is causing the file I/O to fail – Remy Lebeau Mar 16 '18 at 06:39
  • @Someprogrammerdude: Look at the source, MainForm is receiving WM_QUERYENDSESSION and creates the Thread. Therefore message handling is alright... I guess Windows ignores the attempt to create the thread because it tries to logoff. Perhaps you should try to rewrite your thread. It should Keep running until it gets terminated from the outside. For the logmessage you should use a Queue. Don't create an instance for each logmessage. – bepe4711 Mar 16 '18 at 06:48
  • @RemyLebeau, about de I/O fail, this is just an example, the real thread do not save information in files. Thanks! – Guybrush Mar 16 '18 at 14:00
  • @bepe4711, I will try to rewrite the thread. Thanks! – Guybrush Mar 16 '18 at 14:01

0 Answers0