Jump to content

AlexQc

Members
  • Content Count

    3
  • Joined

  • Last visited

Community Reputation

0 Neutral

Technical Information

  • Delphi-Version
    Delphi 10.4 Sydney
  1. Oh great, I knew interacting with UI elements from a TThread was bad but didn't knew how to do it the proper way. I now call the "Add" to the TString wrapped under an anonymous procedure within a "Queue" call. If I wanted to re-raise in the main thread an exception that occurred during the TThread.Execute. How would I do it? I was thinking something like this would work: procedure TDirectoryWorkerThread.Execute; begin try //Do work that can raise an exception except on Exception do begin Self.Synchronize( procedure begin raise; end ); end; end; end; But I get access violations...
  2. The thread is created when the user click a button or when he drag and drop files/directory to the form so yes at that point the TListBox (ListBoxPrograms) is fully created. Since I use a "plain" Delphi TListBox I guess I'm OK? (At least it's working fine here). The thread don't know nothing about the Form (it only receive the TStrings from the form TListBox.Items). In ListFilesDir I just do FindFirst/FindNext in a repeat/until and in the "until" I check for Self.Terminated. When I find something I want, I do a plain Buffer.Add (TStrings.Add) to add the string to the list. I'm not sure if it's safe since the TStrings is from a VCL component... If not, do you have an example with a Synchronized or Queued method? For the rest of your comments I already handle exceptions (I handle them silently - no need to report to the user). Thank you for your help!
  3. I'm back to coding Windows applications and I'm using Delphi 10.4. Everything is working: no memory leak, no race conditions, no deadlocks... I'm pretty sure everything is OK but since it's my first time (seriously) using TThread in a Windows application I want to double check that I didn't do something bad! Code simplified for readability: type TDirectoryWorkerThread = class(TThread) private Parameters: TDirectoryWorkerParams; //Record Target: TStrings; procedure AddToTarget(const Item: String); procedure ListFilesDir(Directory: String); public constructor Create(CreateSuspended: Boolean; Buffer: TStrings; Params: TDirectoryWorkerParams; OnTerminateEvent: TNotifyEvent = nil); overload; destructor Destroy(); override; procedure Execute(); override; end; TFormMain = class(TForm) procedure FormDestroy(Sender: TObject); private DirWorker: TDirectoryWorkerThread; function DirWorkerBusy(): Boolean; procedure DirWorkerFinished(Sender: TObject); protected procedure WndProc(var Message: TMessage); override; implementation const APPWM_FREE_DIRWORKER = WM_APP + 1; constructor TDirectoryWorkerThread.Create(CreateSuspended: Boolean; Buffer: TStrings; Params: TDirectoryWorkerParams; OnTerminateEvent: TNotifyEvent = nil); begin inherited Create(CreateSuspended); if Assigned(OnTerminateEvent) then Self.OnTerminate := OnTerminateEvent; //Do more initialization... Self.Target := Buffer; end; destructor TDirectoryWorkerThread.Destroy(); begin Self.Parameters.AllowedExtensions.Free; //TStringList inherited; end; procedure TDirectoryWorkerThread.Execute; begin Self.FreeOnTerminate := False; ListFilesDir(Self.Parameters.Directory); end; procedure TFormMain.DirWorkerFinished(Sender: TObject); begin PostMessage(Self.Handle, APPWM_FREE_DIRWORKER, 0, 0); end; function TFormMain.DirWorkerBusy(): Boolean; begin Result := Self.DirWorker <> nil; //Once finished the worker will send a message to be freed so no need to check for status end; procedure TFormMain.DirWorkerFinished(Sender: TObject); begin PostMessage(Self.Handle, APPWM_FREE_DIRWORKER, 0, 0); end; procedure TFormMain.WndProc(var Message: TMessage); begin if Message.Msg = APPWM_FREE_DIRWORKER then FreeAndNil(Self.DirWorker) else inherited; end; procedure TFormMain.FormDestroy(Sender: TObject); begin if DirWorkerBusy() then FreeAndNil(Self.DirWorker); end; //Thread created on a user event: Self.DirWorker := TDirectoryWorkerThread.Create(False, ListBoxPrograms.Items, ThreadParams, DirWorkerFinished); //Thread can be cancelled like this: if (Key = VK_ESCAPE) and DirWorkerBusy() then FreeAndNil(Self.DirWorker);
×