Jump to content
Aamgian

Thread Issues: using resume and start

Recommended Posts

Posted (edited)

Hello,

 

simple code that I made:

TThread.CreateAnonymousThread(procedure
  begin
    TThread.Synchronize(nil, procedure
    begin
      HeaderLabel.Text := 'My Job';
    end);
  end).Resume;

when the target Android 64bit compile, using the application resume runs smoothly.

 

Meanwhile, if you use Start to call the thread, error message will appear "cannot call start on a running or suspended thread"

TThread.CreateAnonymousThread(procedure
  begin
    TThread.Synchronize(nil, procedure
    begin
      HeaderLabel.Text := 'My Job';
    end);
  end).Start;

this case only happened on some android devices target android 64bit, but if the target is 32bit the error message does not appear.

has anyone experienced something similar? and what is the solution?

 

device with sdk 30.

 

Thank you

Edited by Aamgian

Share this post


Link to post

Just as an information, here is what the documentation says about CreateAnonymousThread(..):

Quote

This thread is created as suspended, so you should call the Start method to make the thread run. The thread is also marked as FreeOnTerminate, so you should not touch the returned instance after calling Start.

 

That directly contradicts your error message

Quote

cannot call start on a running or suspended thread

Strange.

Share this post


Link to post
3 hours ago, Der schöne Günther said:

Just as an information, here is what the documentation says about CreateAnonymousThread(..):

That directly contradicts your error message

Strange.

precisely because I found something strange I asked, some friends did not believe what I was experiencing. I'll send you a video clip so you can see it.

Share this post


Link to post
3 hours ago, Fr0sT.Brutal said:

Btw, thread.Resume is considered bad practice and deprecated since XE

therefore I am looking for a way to solve this problem so that I can use Start.

Share this post


Link to post
7 minutes ago, Aamgian said:

precisely because I found something strange I asked, some friends did not believe what I was experiencing. I'll send you a video clip so you can see it.

I don't think @Der schöne Günther was doubting you, just noting that what you were doing seemed correct. Can you make an MCVE and submit a report to Quality Portal?

Share this post


Link to post
6 minutes ago, David Heffernan said:

I don't think @Der schöne Günther was doubting you, just noting that what you were doing seemed correct. Can you make an MCVE and submit a report to Quality Portal?

sorry if I respond wrongly to what was conveyed by @Der schöne Günther,

i will try to make report to Quality Portal, I am trying to ask here, maybe someone has experienced something similar.

Share this post


Link to post

I don't have the source for the latest version to look at, but in XE3 (the last version I do have source for), that specific error message only occurs under these conditions:

 

- (Windows only) calling Start() on a running thread, or a thread that has had Suspend() called on it more than once before Start().

- calling Start() on a thread that has already finished, but not been destroyed yet

- calling Start() on a thread created by reading TThread.CurrentThread in a thread context that is not owned by a TThread.

 

None of those conditions apply to your TThread.CreateAnonynousThread() example.  Calling Start() on such a thread is absolutely the correct thing to do.  So this has to be a bug that Embarcadero has introduced in a recent version and will have to fix.

Share this post


Link to post
2 hours ago, Remy Lebeau said:

I don't have the source for the latest version to look at, but in XE3 (the last version I do have source for), that specific error message only occurs under these conditions:

 

- (Windows only) calling Start() on a running thread, or a thread that has had Suspend() called on it more than once before Start().

- calling Start() on a thread that has already finished, but not been destroyed yet

- calling Start() on a thread created by reading TThread.CurrentThread in a thread context that is not owned by a TThread.

 

None of those conditions apply to your TThread.CreateAnonynousThread() example.  Calling Start() on such a thread is absolutely the correct thing to do.  So this has to be a bug that Embarcadero has introduced in a recent version and will have to fix.

I have tried using Samsung and Xiaomi brand devices with SDK 30 but this error does not occur. is there a role for the device in causing this to happen?

as a note the device with the Vivo brand that I use is the latest release.

Share this post


Link to post
4 hours ago, Aamgian said:

is there a role for the device in causing this to happen?

The device should not matter, no. This is strictly an RTL error message that TThread.Start() raises if it can't resume a suspended thread, either because the thread is not allowed to resume (e, it is already finished), or the OS failed to resume the thread properly.  Hard to say for sure what is going on without seeing the latest source code for TThread.

 

Share this post


Link to post
50 minutes ago, Remy Lebeau said:

The device should not matter, no. This is strictly an RTL error message that TThread.Start() raises if it can't resume a suspended thread, either because the thread is not allowed to resume (e, it is already finished), or the OS failed to resume the thread properly.  Hard to say for sure what is going on without seeing the latest source code for TThread. 

 

I replaced all CreateAnonynousThread in my project with ITask and all works fine.

thank you

 

procedure THeaderFooterForm.Button1Click(Sender: TObject);
var
 aTask: ITask;
begin
 aTask := TTask.Create(
   procedure
   begin
     TThread.Synchronize(TThread.Current,
       procedure
       begin
         HeaderLabel.Text := 'My Job';
       end);
   end);
   aTask.Start;
end;

 

Share this post


Link to post

Not sure about waht you need to do,  TL;DR;

but why not exchange

TThread.Synchronize(TThread.Current,

to

TThread.Queue(TThread.Current,

For a simple notification in the UI, like a Label text, that should be good enough, and decouples much better.

  • Like 1

Share this post


Link to post
12 hours ago, Rollo62 said:

For a simple notification in the UI, like a Label text, that should be good enough, and decouples much better.

If the sole purpose of the thread is just to delay a UI notification, then TThread.ForceQueue() would be better, no thread needed at all:

procedure THeaderFooterForm.Button1Click(Sender: TObject);
begin
  TThread.ForceQueue(nil,
    procedure
    begin
      HeaderLabel.Text := 'My Job';
    end
  );
end;

 

  • Like 1

Share this post


Link to post
On 3/20/2021 at 3:39 AM, Remy Lebeau said:

If the sole purpose of the thread is just to delay a UI notification, then TThread.ForceQueue() would be better, no thread needed at all:


procedure THeaderFooterForm.Button1Click(Sender: TObject);
begin
  TThread.ForceQueue(nil,
    procedure
    begin
      HeaderLabel.Text := 'My Job';
    end
  );
end;

 

The code that I will use is actually a lot more, especially for doing the calculation process and making requests to the server.

thank you for the advice you give.

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

×