[Lazarus] custom thread reading file does not respond properly

Sven Barth pascaldragon at googlemail.com
Tue Sep 5 22:51:04 CEST 2017


On 05.09.2017 21:43, Andrea Mauri via Lazarus wrote:
> 
>     I notice that multiple people have already told you not to use a
>     tight loop, and that applies to any OS.
> 
> 
> 
> What exactly means tight? Is it something that I could measure in some way?
> The sample test I submitted to the forum is not my real code, that is a
> little more complex, and it does anything I do. What should I add?
> Since the same code works on win and linux (and as mattias wrote on the
> forum also on Mac). But not on my Mac (I can see the label changing but
> I cannot interact with my form), I supposed that it could be related to
> SSD drive.
> I didn't find a definitive answer. 
> Anyway what is your suggestion? What should I add?

It doesn't have to do with the SSD, this even happens on my old
PowerBook which is much less powerful and doesn't even have an SSD
(though I still plan to change that, mind you :P ).

It is however solved if you add a "Yield;" after the Synchronize call.
So my suspicion is that the scheduling of Mac OS X is somehow messing
things up. Either the scheduling is favoring the one thread while it
shouldn't (though even reducing the priority doesn't help) or the UI
framework of Mac OS X (and whatever else is involved in the main thread)
is so heavy weight that the timeslice of the mainthread is used up more
often than not thus leading to the read thread being scheduled much more
often.
By using Yield (or also Sleep(), but Yield is without any pause) the
thread is explicitly giving up its timeslice and that seems to be enough
here...

Sidenote: you might want to change your code a bit so that it looks like
this:

=== code begin ===

TMyThread = class
private
  fStatusMessage: String;
  procedure DoStatusEvent; // this will be passed to DoSynchronize
  procedure StatusEvent(const aStatus: String); // this will set
fStatusMessage and call Synchronize
  ...
end;

procedure TMyThread.StatusEvent(const aStatus: String);
begin
  fStatusMessage := aStatus;
  Synchronize(@DoStatusEvent);
  //Yield; // <- you can add this here
end;

=== code end ===

This is a bit cleaner as it keeps changes to the status handling in one
location. :)

Regards,
Sven


More information about the Lazarus mailing list