Delphi Thread pool Queue - multithreading

Hi is it possible to find an example for the follow task.
I am connecting on a Webscocket and i recive messages.
after the message received i have to insert it to a database and i try to do it in a Queue Thread pool.
at the moment i do the follow but i dont think is the corect way to do it.
var MyStrings:Tstringlist;
MyStrings:Tstringlist.create;
//On Websocket message
MyStrings.add(Message);
//and in a Thread that always is Running i do
procedure TMythread.Execute;
begin
while true
begin
if MyStrings.count>0 Then
begin
/////////////////////////////////////
//database jobs
//with the string MyStrings.strings(0)
/////////////////////////////////////
MyStrings.delete(0);
end;
end;
end;
but this way i proccess the jobs one by one how is possible to have 10 threads at the same time to process the tasks
and after the 10 threads finish to pop 10 more Strings from Mystrings if exists and process them to 10 seperate Threads?

First, you have to make your data exchange save. If you've a list which will be changed (add, remove entries) over different threads, you have to lock the resource.
For thread queue/pool have a look at below links:
http://docwiki.embarcadero.com/Libraries/Rio/en/System.Threading.TTask
http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread.Queue

Related

Delphi TIdTcpServer force stop IdSync after someTimeOut

I need to develop a TCP server and client with persistent connections using Indy and Delphi XE2. Almost everything is going well.
This service is a critical service, so I need to put in some protection in the server to prevent unnecessary processing or freezes. Because of this, I create a thread to check a timeout for critical processes.
I made this TIdSync class:
type
TSync = class(TIdSync)
protected
procedure DoSynchronize; override;
end;
procedure TSync.DoSynchronize;
var
oTimeOut: TThreadTimeOut;
begin
...
oTimeOut := TThreadTimeOut.Create(AContext, WaitTimeOut*2, Self);
oTimeOut.Start;
...
// the code below is just a test, **this is the key to my question**
// if something goes wrong in any subroutine of DoSynchronize, I want
// to stop execution of this object and destroy it. In the thread above
// I want to test when the timeout elapses. If this IdSync object still
// exists and if this routine is still executing, I want to stop execution
// of any routine or subroutine of this object to avoid freezing the
// service and stop memory consumption and CPU usage
while true do begin
Sleep(100);
end;
//If everything is OK
oTimeOut.Stop;
end;
procedure TThreadTimeOut.execute;
var
IniTime: DWORD;
begin
IniTime := GetTickCount;
while GetTickCount < IniTime + TimeOut do begin
Sleep(SleepInterval);
if StopTimeOut then
Exit;
end;
if ((Terminated = False) or (StopTimeOut)) and (IoHandler <> nil) then begin
IOHandler.Connection.IOHandler.Close;
IdSync.Free; //here I try to make things stop execution but the loop to test is still running
end;
end;
This code above works fine to stop receiving and sending data when the timeout elapses, but not to stop execution of TIdSync. How can I do that?
There is no timeout logic in TIdSync (largely because there is no timeout logic in TThread.Synchronize(), which TIdSync uses internally).
You cannot destroy a TIdSync object while it is running. A synced procedure cannot be aborted prematurely once it has been queued for execution, or has started running. It must be allowed to run to completion.
TIdSync.DoSynchronize() (or any method synced with TThread.Queue() or TThread.Synchronize()) is executed in the context of the main UI thread. Long-running code should be executed in its own thread, not in the main UI thread. Make sure the main UI thread is not blocked from processing new messages and sync requests in a timely manner.
If you want to stop a synced procedure, you need to have it handle a TEvent object or other flag which worker threads can signal when needed, and that the procedure checks periodically so it can exit as soon as possible (either gracefully or by raising an exception).
Synched operations of any nature should be short, to prevent blockages/deadlocks, resource starvation, etc. You need to re-think your design. You are doing things the wrong way.

how to get count for terminated threads?

hello friends i have a doubt regarding thread count. i have some code written below for thread
Procedure Mainthread.execute;
var
I : integer;
ScannerCh : array of ScannerChild; //array of ScannerChild
IpList : TStringlist;
IPs: Integer; //ipcount is count of iplist
Begin
IpList:=TStringList.Create;//creating stringlist
IPs := IpList.Count; //Ipcount is given value of iplists count
SetLength(ScannerCh, IPs); //Setting length of scannerch as ipcount
I:=0;
Repeat
While getthreadscount(getcurrentprocessid) >= tcount + 1(for main thread + Scannerch threads) do //Checking if is greater than tcount(thread input) by user
Sleep(30);
ScannerCh[I]:=ScannerChild.Create(True, IpList[i]);
ScannerCh[I].FreeOnTerminate:=True;
ScannerCh[I].LvHostname := LvHosts;
ScannerCh[I].Resume;
I:=I+1;
Sleep(20); //Sleep after each thread is created so that threads will enter critical section properly
until I = IPs;
end;
Scannerchild thread does some work. my code works perfectly if i have only these threads in process. If there are some other threads running to then i will be in trouble getting threadscount by getthreadscount function and i will not get to know which threads are getting terminated by getthreadcount function. so how can i enhance my code for many threads working. My logic is when scannerch thread terminates it should decrement count variable and when it gets created it should increment count variable. so that it will not be any problem if other threads are terminated or not. i just want to deal with scannerch thread termination and need to get counts of instances of running threads of scannerch. so that i put count variable instead of getthreadscount and my problem will be solved
Well, the question is easy enough to answer. Declare a count variable in the main thread class:
FScannerChildCount: Integer;
Whenever you create a new thread, increment this variable. Whenever a thread terminates, decrement it.
The incrementing is easy to do since you create the threads quite clearly and explicitly in the main thread code.
As for the decrementing, you need an OnTerminate event handler for each scanner child thread instance. This executes in the context of the process main thread, rather than your MainThread thread. FWIW, MainThread is a terrible name since everyone takes main thread to mean the main process thread. Because the OnTerminate event doesn't run in the same thread as your MainThread thread, you'll need synchronization.
When you increment the thread, use InterlockedIncrement. And when you decrement, use InterlockedDecrement.
The OnTerminate handler might look like this:
procedure MainThread.ScannerChildTerminate(Sender: TObject);
begin
InterlockedDecrement(FScannerChildCount);
end;
And you assign the event like any other event handler:
ScannerCh[I] := ...;
....
ScannerCh[I].OnTerminate := ScannerChildTerminate;
....
ScannerCh[I].Resume;
All of this said, whilst this may be the answer to the question you asked, you are attempting to solve your problem the wrong way. You should be using a thread pool to simplify the coding and avoid the overhead of creating and destroying short lived threads.

Delphi not all threads executing simultaneously

I have the following scenario:
The program I am writing simulates multiple air networks. Now I have written it so that each simulation is in its own thread with its own data. This is so that there can be no contamination of data and each thread is complete multitasking safe. I have implemented delphi's native TThread class for each thread.
The program has one main thread. It then creates multiple sub threads for each network (my current test case has 6). But each sub thread also has 4 additional threads since its network has more than one layout. So in total I have 31 threads, but only 24 threads actively processing. All threads are created in suspended mode so that I can manually start them.
The computer I am running on is an i5 laptop so it has 4 threads (2 physical cores + 2 HT). In the production environment this will run on servers so they will have more processing power.
Now in the main program thread I have added a break point after the for loop which executes the threads. This doesn't trigger immediately. Watching the debug console of Delphi, it looks like it is only actively running 4 threads at a time. As soon as one exits, it starts another thread.
The simulations in the threads are difficult to optimize and require a few loops to finish the simulation. And each loop requires the previous loop's data. But each simulation is completely independent of the next so the program is an excellent candidate for threads and pipe lining.
Now my question is why does it only start 4 threads and not all the threads as the code specifies?
EDIT Added pieces of code
Main program
for i := 0 to length(Solutions)-1 do
begin
Solutions[i].CreateWorkers; //Setup threads
end;
for i := 0 to length(Solutions)-1 do
begin
Solutions[i].Execute; //start threads
end;
end;
isSolversBusy := false; //breaking point doesn't trigger here
1St level of threads
procedure cSolution.Execute;
var
i : integer;
lIsWorkerStillBusy : boolean;
begin
lIsWorkerStillBusy := true;
for i := 0 to length(Workers)-1 do
begin
Workers[i].Start;
end;
while (lIsWorkerStillBusy) do
begin
lIsWorkerStillBusy := false;
for i := 0 to length(Workers)-1 do
begin
if Workers[i].IsCalculated = false then
begin
lIsWorkerStillBusy := true;
end;
end;
sleep(100);
end;
FindBestNetwork;
IsAllWorkersDone := true;
end;
2nd level of threads
procedure cWorker.Execute;
begin
IsCalculated := false;
Network.UpdateFlows;
Network.SolveNetWork; //main simulation work
CalculateTotalPower;
IsCalculated := true;
end;
EDIT 2
The reason I create them all suspended is because I store them in an array and before I start them I first have create the workers and their properties. I am simulating air network scenarios. Each solution is a different layout, while each worker is a different way of running that layout.
I have to first calculate all the worker's start properties before I start them all. In hind sight I could modify the code to do that in the thread. It currently happens in the main thread. The creation of the threads happens before the piece of code I pasted here.
The reason I keep them all in threads is that I need to evaluate the results of each thread afterwords.
This is your problem :
for i := 0 to length(Solutions)-1 do
begin
Solutions[i].Execute; //start threads
end;
This does not start the threads - this is executing the Execute method in the calling thread. In fact you were not running only 4 threads at a time, you were not even running one - all of this work would be done on the main thread sequentially. To resume a suspended thread you must use Solutions[i].Start.
The Execute method of a TThread is a special method that is executed on the worker thread created by the TThread automatically. When you create a TThread this method is automatically run on the worker thread that the TThread creates. If you create the thread suspended then it simply waits for you to wake the thread before beginning this work. Calling the .Start method of a TThread is what accomplishes this - triggering the underlying worker thread to begin executing the .Execute method.
Otherwise, the Execute method, and all other methods of a TThread are no different from any other normal method belonging to a class. They can be executed on any thread that calls them directly.
In this case, it doesn't seem like you are doing any additional work in the main thread between creating and executing your workers. In this case, unless you have an explicit need for it, you could simply create your threads not-suspended and let them execute automatically upon creation.

Sending data from TThread to main VCL Thread

I'm writing some software that talks to external hardware via a dll (moving some motors and reading some values back). The calls to the dll are blocking and may not return for in the order of 10 seconds. The software performs a scan by moving the hardware, taking a reading and repeating for a number of points. One scan can take in the order of 30 minutes to complete. While the scan is running I would obviously like the GUI to be responsive and a live graph (in an MDI Child) of the incoming data to be updated at each point. Multithreading seems the obvious choice for this problem.
My question is, what is the best way to thread this and talk back to the main VCL thread to update the graph during a scan?
I currently have a single TThread descendant that performs the 'scan logic' and an array of doubles in the public var section of the ChildForm. I need to fill out this array from the thread but I don't know whether to use Synchronize or CriticalSection or PostMessage or some other method. Each time a new value is added, the main VCL thread needs to update the graph. Should I really have an intermediary object for the data that is a global var and access this from the Thread and the ChildForm separately somehow?
The simplest way to update the GUI from a thread is to use anonymous methods in conjunction with TThread.Synchronize and TThread.Queue.
procedure TMyThread.Execute;
begin
...
Synchronize( // Synchronous example
procedure
begin
// Your code executed in main thread here
end
);
...
Queue( // Asynchronous example
procedure
begin
// Your code executed in main thread here
end
);
end;
Passing values asynchronous often requires "capturing" a value.
procedure TMyThread.PassAValue(anInteger: Integer);
begin
Queue(
procedure
begin
// Use anInteger in main thread
end
);
end;
procedure TMyThread.Execute;
var
myInt: Integer;
begin
...
PassAValue(myInt); // Capture myInt
...
end;
When an anonymous method is using a variable, the reference to the variable is captured.
This means that if you alter the variable value before the anonymous method is executed, the new value is used instead. Hence the need to capture the "value".
A more elaborate example can be found here, synchronize-and-queue-with-parameters, by #UweRaabe.
If you want to invest a little more then a simple Synchronize call which by the way blocks the main thread, you can add a simple FIFO queue with messaging on top of it. The flow of data would be like this:
The thread puts the data into the queue.
The thread post a message to the main thread window. Which one I don't care :)
You handle the message that data is available and process any messages in the queue as you see fit.
The code would look something like this:
the queue...
const
WM_DataAvailable = WM_USER + 1;
var
ThreadSafeQueue: TThreadSafeQueue;
the data is put into the queue...
procedure PutDataIntoQueue;
var
MyObject: TMyObject;
begin
MyObject := TMyObject.Create;
ThreadSafeQueue.Enqueue(MyObject);
PostMessage(FMainWindowHandle, WM_DataAvailable, 0, 0);
end;
and processing...
procedure ProcessDataInTheQueue(var Msg: TMessage); message WM_DataAvailable;
procedure ProcessDataInTheQueue(var Msg: TMessage);
var
AnyValue: TAnyValue;
MyObject: TMyObject;
begin
while ThreadSafeQueue.Dequeue(AnyValue) do
begin
MyObject := TMyObject(AnyValue.AsObject);
try
// process the actual object as needed
finally
MyObject.Free
end;
end;
end;
The code is written without Delphi and checks so it can contain errors. I showed the example using my freely available thread safe queue and TAnyValue. You can find both here:
http://www.cromis.net/blog/downloads/
Also please note then I did not do any check if PostMessage was actually sent. You should check that in production code.
I find that populating a TThreadList from the background thread, then posting a message to the main thread that there is a new item in the list, then processing the list in the main thread is simple and easily maintainable.
With this method, you could store as many readings as you wanted in the list, and every time the main thread received a message, it would simply process all the items in the list at once.
Define a class for the readings, instantiate them, and add them to the list in the background thread. Don't forget to free them in the main thread when you pop them off the list.
Use postmessage inside you thread and send messages to main form handle.
Register one (or more) custom messages and write a handler for them.
const WM_MEASURE_MESSAGE = WM_USER + 1;
Create a thread class, add a MainFormHandle property (Thandle or cardinal).
Create thread suspended, set MainFormHandle with main form handle, then resume thread.
When you have a new measure, assign data1 and data2 dword with some data from measure, then
PostMessage(fMainFormHandle,WM_MEASURE_MESSAGE,data1,data2);
In main form you have message handler:
procedure MeasureMessage(var msg: TMessage); message WM_MEASURE_MESSAGE;
begin
// update graph here
// msg.wparam is data1
// msg.lparam is data2
end;
If you need to send much more data from thread to main form, you can create an appropriate structure in main context for the whole measurement data, pass a reference to thread, let the thread write data and use messages just to tell main form new data position (an array index, for example). Use TThread.Waitfor in main context to avoid freeing data structure while thread is still running (and writing into memory).

Periodical tasks in Delphi app

I'm developing an application that should perform certain sql queries in different MSSQL servers after specified intervals. My thoughts are about make an array of threads and in each thread run timer in which task will run. Does it really needs to make each thread for each timer, or should I just distinguish one timer for each task (whatever timer will produce thread)? Any thoughts about implementation?
Thanks a lot, guys!
I doubt that you need to have one thread per task. It would probably suffice to create one timer per task. If a timer fires whilst another task is running then the second task will have to queue up but it doesn't sound like that will be a great problem.
If you are going to use a Delphi TTimer to do this you'll need to make sure that your service has a message queue and runs a message loop on that queue. You may wish to run that message queue on a separate thread but if you do make sure that the TTimer objects are created on that thread so that they are associated with the right message queue.
You ask in the comments how to run a message loop in a thread. The following code should suffice:
repeat
try
Application.HandleMessage;
except
Application.HandleException(Application);
end;
until Terminated;//this is the Terminated property of the thread
This will give you all the bells and whistles of the Delphi message loop. If you want a very standard message loop you can use this:
procedure PerformThreadLoop;
var
Msg: TMsg;
begin
repeat
Try
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
WaitMessage;
Except
Application.HandleException(Self);
End;
until Terminated;//this is the Terminated property of the thread
end;
If all you want is to pump WM_TIMER messages both will work but I personally would be inclined to go with the second option, the raw Win32 API version.

Resources