FAQ.MultiThreading
Main page -> FAQ -> MultiThreading
Contents
Introduction
When dealing with applications that need several connections, often using threads come up. Why that ? Mainly because the idea to use (if it's a client) or to serve (if it's a server) several sockets - ie several connections - means using or serving them concurently. And, the easiest way to understand "concurently" is to say "doing several thing at the same time" and them comes up the Threads, the multitasking, etc...
Although with ICS it's not primarily necessary, as ICS is based on the Asynchronous Paradigm, sometimes threads have to be used.
But before to see why and how to use threads with ICS, let's define what is a thread : "Threads are a way for a program to split itself into two or more simultaneously running tasks [...] Threads are similar to processes, but differ in the way that they share resources " (Wikipedia's Thread (computer_science)). By extension, MultiThreading is the ability for a processus to have several Threads.
- Advantages :
- run concurently with other threads if the code is thread safe ;
- the ability to use several processor ;
- Disadvantages
- for the OS, switching from a thread context to another thread context takes some time - a few ticks. Using several threads on a mono processor system may at the end cause some unneeded CPU overhead, meaning slowing your application ;
- resources sharing has to be managed carefully (concurent access, dead lock, ...)
- With Delphi, VCL - ie all the GUI stuff - is not Thread safe.
The Main Question
Do i need Threads ?
Or, practically, how to determine the use of threads ? As mentioned earlier, ICS is based on the Asynchronous Paradigm. It means that if you plan to use threads just because there'll be several simultaneous sockets/connections, this is definitely not needed. By the same way, if you plan to use on thread per connection because you think that TCP/IP sockets I/O are blocking and that you don't want the main process to be frozen because of a I/O waiting state, again, it's not needed at all, still because of the Asynchronous model used by ICS.
But, there're situations where using threads may be very useful :
- the number of concurrent connections (I/O) is too high for a single processor and then you need to use several processors ;
- some job needs to be done during a connection (ie getting data from a COM port, building an HTML page with a SQL query result) and may be lengthy or blocking and would freeze the main - GUI - process which has to wait for the job to be done before serving any other connection ;
Cases where needed and where not needed
A Thread per Socket
When incoming connection, encapsulating socket within a thread, and managing communication within the thread, across several threads
Many sockets per thread
A single thread is able to handle a lot of simultaneous sockets. Using a single socket per thread is not the way to go to support a large number of concurrent connections. In that case you need to use many socket per threads. Something like 10 to 500 sockets per thread. This way you can handle thousand simultaneous connections.
A Worker Thread
When running a lengthy process (SQLing a RBDMS, doing bottlenecked I/O, ...), and to prevent GUI from freezing, encapsulating it in a thread (JobThread), and sending back data when the thread is done (or simulating a process end).
See Also
Multithreading - The Delphi Way | A good article, with sources, about how to use threads in Delphi |