Bookstore

Recent

Author Topic: Threads, Memos and synchronising between them  (Read 485 times)

hdrz

  • New member
  • *
  • Posts: 8
Threads, Memos and synchronising between them
« on: February 28, 2020, 08:37:39 am »
Hi all,

I have some old code that I need to revise and upgrade. The code essentially starts some processes using TThreads. Each thread has an associated TMemo (shown or hidden, but always present) which it fills with text. In order to proceed, I have a few questions about how to design such a thing. (The old code is working, but is not thread safe and is very hairy..)
  • Currently the main worker class is inherited from TThread with all the methods and properties under this object. I did some searching and found that usually the worker class is inherited from Object, with TThread as a private field, see for example https://www.freepascal.org/~michael/articles/lazthread/lazthread.pdf. Which is the right way?
  • How would you handle the synchronisation between the different threads and the associated TMemos? What is the correct way to store the TMemos pointers and access them from the worker objects?
I appreciate any info on the subject. Thanks all.

PascalDragon

  • Hero Member
  • *****
  • Posts: 1092
  • Compiler Developer
Re: Threads, Memos and synchronising between them
« Reply #1 on: February 28, 2020, 09:03:57 am »
Currently the main worker class is inherited from TThread with all the methods and properties under this object. I did some searching and found that usually the worker class is inherited from Object, with TThread as a private field, see for example https://www.freepascal.org/~michael/articles/lazthread/lazthread.pdf. Which is the right way?

There really is no right no wrong. In the end it depends on how your object structure works best. In most cases I've seen it's TThread that's extended.

How would you handle the synchronisation between the different threads and the associated TMemos? What is the correct way to store the TMemos pointers and access them from the worker objects?

GUI objects must only be accessed by the main thread (some widgetsets like Qt explicitly check that). Thus any code that accesses a GUI object should do so through TThread.Synchronize, TThread.Queue or Application.QueueAsyncCall with all implications these bring with them.

avra

  • Hero Member
  • *****
  • Posts: 1827
    • Additional info
Re: Threads, Memos and synchronising between them
« Reply #2 on: February 28, 2020, 12:46:53 pm »
How would you handle the synchronisation between the different threads and the associated TMemos?
TMemoChannel from MultiLog might not be exactly what you want, but it might be worth a look since it allows dozens of threads to write to memo without any locking and slowdown. I have used QueueAsyncCall for that, which is very nice and powerful. The only drawback I see is luck of Delphi compatibility.
https://github.com/blikblum/multilog/blob/master/memochannel.pas

Here is a wiki article on using QueueAsyncCall:
https://wiki.freepascal.org/Asynchronous_Calls
« Last Edit: February 28, 2020, 12:51:15 pm by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

hdrz

  • New member
  • *
  • Posts: 8
Re: Threads, Memos and synchronising between them
« Reply #3 on: February 28, 2020, 01:11:28 pm »
@PascalDragon - Thank you, but as stated in the beginning of the question there is already an application I want to upgrade, so I know all the basics. I am looking for a high level point of view on the subject, as to how to manage the different memos and threads, for example how a certain thread knows to which memo to write (or maybe it doesn't know and the main application is doing the routing?), that sort of things.

@avra - Funny, I found your application somewhere else on the forum and was already looking at the code! However, in my case there may be several threads, each writing to it's own memo.

winni

  • Hero Member
  • *****
  • Posts: 1114
Re: Threads, Memos and synchronising between them
« Reply #4 on: February 28, 2020, 01:20:38 pm »
@avra

Just had a look at the memochannel.

One question: With the use of QueueAsyncCall you get around the synchronize of threads?

Winni

devEric69

  • Sr. Member
  • ****
  • Posts: 254
Re: Threads, Memos and synchronising between them
« Reply #5 on: February 28, 2020, 01:27:49 pm »
For information, if you don't use SQL (the logging of when\what\where SQL queries are not yet stabilized), the fork https://github.com/devEric69/multilog/blob/master/README.md does the same thing, but is easier to use quickly (amo).
==> At the very least, the few explanations and screenshots will allow you to understand faster the concept of Multilog.
use: Linux 64 bits (Ubuntu 18.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

avra

  • Hero Member
  • *****
  • Posts: 1827
    • Additional info
Re: Threads, Memos and synchronising between them
« Reply #6 on: February 28, 2020, 02:09:44 pm »
One question: With the use of QueueAsyncCall you get around the synchronize of threads?
Yes. QueueAsyncCall simply puts in a serialized thread safe way 2 pointers (1 for method and 1 for data) into a queue. Then just before time comes for GUI update (either by OS or forced with Application.ProcessMessages) your main application thread stops execution of your code and calls all methods from the queue. It is simple as that with thread locking and syncing completely avoided. Only one thread has GUI access, so no problems at all with GUI updating from other threads.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

winni

  • Hero Member
  • *****
  • Posts: 1114
Re: Threads, Memos and synchronising between them
« Reply #7 on: February 28, 2020, 02:45:51 pm »
Good News!

Thanx

Winni