Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2012-08

Help: Multithreading

8 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Clinton Shane Wright

Hi everyone,

I hope that someone can help me understand a little bit better on how to work with threads in Lazarus. I am still learning so please forgive my ignorance in any matter here. I am using the multithreading.lpi example supplied with lazarus and I create a type TMyThread of class TThread and I have the Execute and other procedures made for the TMyThread thread. I have got the thread running well, but now I dont understand how to make another instance of the same thread and how write my code to identify which instance is running so that I can assign different tasks to each thread individually.

On Form Create Procedure I have (as in the mulithreading example), MyThread := TMyThread.Create(False); This creates and instance of the type TMyThread. I got that. I got that working. Now with the same procedures if I go ahead and create another instance in the On Form Create Procedure, MyThread2 := TMyThread.Create(False); How do I use this second instance to do different work in the same procedures. I hope that whoever reads this can get what I am saying. I will post a link to the code below and I hope that someone can advise me. Any help is much appreciated.

If I may add, I am using the thread to read data from a modem from the RS232, but now I have more than one modem connected to the system that I need to read from at once and having it run in one thread gets slower as I add one modem extra to the thread, I want to use the second instance, TMyThread2 to control the modem 2.

http://www.heypasteit.com/clip/0FVU

Please I am desperate to know how to use this correctly.

Thank you kindly.

Clinton Wright
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20120815/65479182/attachment.html>

Reply by email

Mattias Gaertner
to Clinton Shane Wright

Clinton Shane Wright hat am 15. August 2012 um 17:20 geschrieben:

Show quoted text 20 lines
Hi everyone, I hope that someone can help me understand a little bit better on how to work with threads in Lazarus. I am still learning so please forgive my ignorance in any matter here. I am using the multithreading.lpi example supplied with lazarus and I create a type TMyThread of class TThread and I have the Execute and other procedures made for the TMyThread thread. I have got the thread running well, but now I dont understand how to make another instance of the same thread and how write my code to identify which instance is running so that I can assign different tasks to each thread individually. On Form Create Procedure I have (as in the mulithreading example), MyThread := TMyThread.Create(False); This creates and instance of the type TMyThread. I got that. I got that working. Now with the same procedures if I go ahead and create another instance in the On Form Create Procedure, MyThread2 := TMyThread.Create(False); How do I use this second instance to do different work in the same procedures. I hope that whoever reads this can get what I am saying. I will post a link to the code below and I hope that someone can advise me. Any help is much appreciated.

You can set variables of MyThread2 before starting it:

MyThread2 := TMyThread.Create(True);
MyThread2.Flag := 2;
MyThread2.Start;
Show quoted text 11 lines
If I may add, I am using the thread to read data from a modem from the RS232, but now I have more than one modem connected to the system that I need to read from at once and having it run in one thread gets slower as I add one modem extra to the thread, I want to use the second instance, TMyThread2 to control the modem 2. http://www.heypasteit.com/clip/0FVU <http://www.heypasteit.com/clip/0FVU> Please I am desperate to know how to use this correctly.

Mattias
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20120815/c01fdd81/attachment.html>

Reply by email

Michael Schnell
to Clinton Shane Wright: I hope that someone can help me understand a little bit better on how to work with…
Clinton Shane Wright wrote
I dont understand how to make another instance of the same thread

That is easy, but you might need to take so afterthoughts:

You can just do something like

var MyThread = array [0..10] of TMyThread;
   for i = 0 to 10 do MyThread[i] = TMyThread.Create(False);

So you have multiple threads that use the same executable code.

Of course global variable are shared between all of them and MyThread[i].xyz (or just xyz from within a TMyThread.ppp procedure) variables are dedicated to each.

Moreover you can do "threadvar" variables that automatically are dedicated to a single thread and not accessible from other threads (including the main thread that gets it's own copy.

These threadvars e.g. can allow to determine which thread is just running in a procedure called by the thread Execute that does not get the TMythread self pointer.

Show quoted text 6 lines
If I may add, I am using the thread to read data from a modem from the RS232, but now I have more than one modem connected to the system that I need to read from at once and having it run in one thread gets slower as I add one modem extra to the thread, I want to use the second instance, TMyThread2 to control the modem 2.

The main problem will be to do the communication between the multiple threads and the main thread.

Here IMHO a good idea is to do the basic receive-protocol in a thread (that most of the time will be blocked waiting for input from the serial interface), and to the more complex stuff (that needs data from and sends data to multiple serial interfaces) in the main thread.

Here IMHO the way to go is to collect a block of data (by the thread) in a memory area allocated by the thread using an Object or "new", and then push (a pointer to) same in a TThreadList. After pushing the thread creates a main thread event by "ApplicationQueueAsyncCall". On that some time later the event will be called on the "Level" of the main thread. Here all available data blocks can be retrieved and the transport memory on the heap can be released.

Sending data to the serial interface usually can be done right in the main thread becaus the OS provides a decent FoFo buffer for each interface.

-Michael

Reply by email

Mark Morgan Lloyd
to Michael Schnell
Michael Schnell wrote 13 lines
> If I may add, I am using the thread to read data from a modem from the > RS232, but now I have more than one modem connected to the system that > I need to read from at once and having it run in one thread gets > slower as I add one modem extra to the thread, I want to use the > second instance, TMyThread2 to control the modem 2. The main problem will be to do the communication between the multiple threads and the main thread. Here IMHO a good idea is to do the basic receive-protocol in a thread (that most of the time will be blocked waiting for input from the serial interface), and to the more complex stuff (that needs data from and sends data to multiple serial interfaces) in the main thread.

Although it's difficult to make definite points without knowing how the code is interfacing to the port. For example, if it's in a tight loop polling for input then of course things will slow down.

Something like Synaser is a good starting point. Or if you have to use the standard serial.pp at least get the modified version from http://mantis.freepascal.org/view.php?id=18946 which fixes a couple of badly-implemented functions (and adds Windows support).

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Michael Schnell
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote
Although it's difficult to make definite points without knowing how the code is interfacing to the port. For example, if it's in a tight loop polling for input then of course things will slow down.

My suggestion is based on using the serial device in blocking mode and not doing much extended work in the "driver" thread, just handling the basic protocol to receive a block of data.

So there will be no "tight" loop in the thread.

The important point is that there will be no "tight" or long winding loop in the main thread as well, as same works strictly based on events (fired by the GUI and by the "driver" thread.

-Michael

Reply by email

Mark Morgan Lloyd
to Michael Schnell
Michael Schnell wrote 14 lines
On 08/16/2012 11:01 AM, Mark Morgan Lloyd wrote: > > Although it's difficult to make definite points without knowing how > the code is interfacing to the port. For example, if it's in a tight > loop polling for input then of course things will slow down. My suggestion is based on using the serial device in blocking mode and not doing much extended work in the "driver" thread, just handling the basic protocol to receive a block of data. So there will be no "tight" loop in the thread. The important point is that there will be no "tight" or long winding loop in the main thread as well, as same works strictly based on events (fired by the GUI and by the "driver" thread.

Yes, but the OP implied that in his original solution he was polling multiple modems rather than blocking on one device (or, for that matter, using select() on a unix-like OS).

I usually end up using select() in some form, since I usually want to do something like adding "no activity" timing markers to a queue or checking the CD signal.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Michael Schnell
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote
the OP implied that in his original solution he was polling multiple modems rather than blocking on one device

not a good idea at all.

(or, for that matter, using select() on a unix-like OS).

Not necessary when using threads. (But great of course in a not multithreded, not event driven environment. )

-Michael

Reply by email