I am trying to make this program using multi thread with delphi it doesn't seem to be going through multiple items just goes through the last one every time instead of selecting multiple
You can see the pic it will explain that it only goes to the last and not the rest of the items
Any Help is great thanks!
procedure TForm1.Button1Click(Sender: TObject);
var
Index2: Integer;
begin
for Index2 := 0 to ListBox2.Items.Count - 1 do
begin
ListBox2.ItemIndex := Index2;
LastName := ListBox2.Items.Strings[Index2];
with T1.Create do
FreeOnTerminate := True;
end;
end;
Your program runs through the 4 items in your listbox, and for each item it starts a thread (that runs in the background) and then continues with the next item in the listbox - even though the thread hasn't finished processing.
If you in your T1 thread reads the ListBox2.SelectedIndex, then it will most likely read the last item, as your thread will most likely only reach the reading of the SelectedIndex after the FOR loop has finished. Remember that the thread you are starting is running simultaneously as your main thread, ie. your main thread doesn't suddently stop running just because you start a new thread (that's the whole point of multi-threading).
Instead, you should pass the index for the thread to process into the thread as you are creating it, by re-making the Create CONSTRUCTOR to accept a listbox and/or the item to process, or - even better - do the readout of the data you need from the ListBox2 and pass that onto the Create CONSTRUCTOR of the thread. You should not access VCL components from threads - especially not if those same components are updated in the main thread at the same time (which is what is the problem here).
Related
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.
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.
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).
Let's say I have to recursively iterate over items stored in a tree structure in the background and I want to walk this tree using multiple threads from a thread pool (one thread per "folder" node). I have already managed to implement this using several different low and high-level approaches provided by the OmniThreadLibrary.
However, what I haven't figured out yet is how to properly detect that the scan has actually completed, i.e. that every last leaf node has been processed.
I found various examples on the net that either checked whether GlobalThreadPool.CountExecuting + GlobalThreadPool.CountQueued <= 0 or that used a IOmniTaskGroup.WaitForAll(). Unfortunately, none of these approaches appears to work for me. The check always returns True too early, i.e. when there still are some tasks running. None of the examples I looked at used recursion though - and those that did did not use a thread pool - is this maybe just not a good combination in the first place?
Here's a (very) simplified example code snippet of how I'm trying to do this at the moment:
procedure CreateScanFolderTask(const AFolder: IFolder);
begin
CreateTask(ScanFolder)
.SetParameter('Folder', AFolder)
.Schedule();
end;
procedure ScanFolder(const ATask: IOmniTask);
var
lFolder,
lCurrentFolder: IFolder;
begin
if ATaks.CancellationToken.IsSignalled then Exit;
lCurrentFolder := ATask.Param['Folder'].AsInterface as IFolder;
DoSomethingWithItemsInFolder(lCurrentFolder.Items);
for lFolder in lCurrentFolder.Folders do
begin
if ATaks.CancellationToken.IsSignalled then Exit;
CreateScanFolderTask(lFolder);
end;
end;
begin
GlobalOmniThreadPool.MaxExecuting := 8;
CreateScanFolderTask(FRootFolder);
// ??? wait for recursive scan to finish
OutputResult();
end.
One example implementation for the wait that I have tried was this (based on an example found on About.com):
while GlobalOmniThreadPool.CountExecuting + GlobalOmniThreadPool.CountQueued > 0 do
Application.ProcessMessages;
But this appears to always exit immediately right after the "root thread" has finished. Even when I add an artificial delay using Sleep()-calls it still always exits too early. It seems that there occurs a "gap" between one task being struck off the list of executing tasks and the ones that were scheduled inside that task to be added to the list of queued tasks...
Actually, instead of waiting for the scan to finish, I would very much prefer to use an event handler (also, I'd rather not use Application.ProcessMessages as I will need this in form-less applications, too) and I already did try with both IOmniTaskControl.OnTerminated and using a TOmniEventMonitor but as these fire for every finished task I still somehow need to check whether the current one was the last one which again boils down to the same problem as above.
Or is there maybe a better way to create the tasks that would avoid this problem?
A simple way is to count 'folders to be processed' by yourself. Increment a value every
time you create a folder task and decrement it every time a folder is processed.
var
counter: TOmniCounter;
counter.Value := 0;
procedure ScanFolder(const ATask: IOmniTask);
var
lFolder,
lCurrentFolder: IFolder;
begin
if ATaks.CancellationToken.IsSignalled then Exit;
lCurrentFolder := ATask.Param['Folder'].AsInterface as IFolder;
DoSomethingWithItemsInFolder(lCurrentFolder.Items);
for lFolder in lCurrentFolder.Folders do
begin
if ATaks.CancellationToken.IsSignalled then Exit;
counter.Increment;
CreateScanFolderTask(lFolder);
end;
counter.Decrement;
end;
What I usually do is to count all the issued 'folderScan' objects out and count them back in again.
Each time a new TfolderScan is needed, the creating TfolderScan calls a factory for it The factory increments a CS-protected 'taskCount' as well as creating the TfolderScan. Every time a TfolderScan is completed, it calls the 'OnComplete' method of the factory that decrements the CS-protected 'taskCount'. If, in 'OnComplete', the count is decremeted to 0, there can be no TfolderScan left and the whole search most be complete. The thread that manages to decrement the count to 0 can do whatever is needed to signal the completion - PostMessage() a main form or call an 'OnSearchComplete' event.
Just as a side-note : Instead of checking (GlobalOmniThreadPool.CountExecuting + GlobalOmniThreadPool.CountQueued > 0) use (not GlobalOmniThreadPool.IsIdle). This hides implementation details and is more efficient.
I am programming multi-threaded app. I have two threads. On is for transferring some data from device to global data buffer and second is for writing those data to file.
Data from device to buffer is transferring asynchronously. The purpose of second thread should be to wait for specified amount of data to be written in main data buffer and finally to write it to file.
Well the first thread is in DLL and second one is in main app. Temporarily I solve this with events. First thread transfers data from device to main data buffer and counts data and when specified amount of data is transferred it sets an event. The second one waits for event to be signalled and when it is it runs some code for data store. Simple as that it is working.
Thread1.Execute:
var DataCount, TransferedData: Integer;
DataCounter := 0;
while not Terminted do
begin
TransferData(#pData, TransferedData);
Inc(DataCounter, TransferedData)
if DataCounter >= DataCountToNotify then SetEvent(hDataCount);
end;
Thread2.Execute:
hndlArr[0] := hDataCount;
hndlArr[1] := hTerminateEvent;
while (not Terminated) do
begin
wRes := WaitForMultipleObjects(HandlesCount, Addr(hndlArr), false, 60000);
case wRes of
WAIT_OBJECT_0:
begin
Synchronize(WriteBuffer); // call it from main thread
ResetEvent(hndlArr[0]);
end;
WAIT_OBJECT_0 + 1:
begin
ResetEvent(hTerminateEvent);
break;
end;
WAIT_TIMEOUT: Break;
end;
end;
Now I would like to make second thread more independent... so I can make multiple instances of second thread and I don't need to wait for first thread. I would like to move data counting part of code from first thread to second one so I won't need data counting in first thread anymore. First one will be just for data transfer purpose.
I would like to use second one as data counter and to store data. But now I will have to loop and constantly check manually for specified data amount. If I had while loop I will have to add some sleep so second thread will not decrease computer performances but I don't know how long should sleep be while speed of data transfer in firts thread is not constant and thus speed of counting in second thread will vary.
My guess that this code sample is not good:
Thread2.Execute:
var DataCount: Integer;
DataIdx1 := GetCurrentDataIdx;
while (not Terminated) do
begin
if (GetCurrentDataIdx - DataIdx1) >= DataCountToNotify then
begin
Synchronize(WriteBuffer);
DataIdx1 := GetCurrentIdx;
end;
sleep(???);
end;
So my question is what is the best approach to solve that issue with data counting and storing it within second thread? What are your experiences and suggestions?
You have some issues. #LU RD has already pointed one out - don't synchronize stuff that does not need to be synchronized. It's not clear what 'WriteBuffer' does, but the file system and all databases I have used are just fine to have one thread opening a file/table and writing to them.
Your buffer system could probably do with some attention. Is there some 'specified data amount' or is this some notional figure that allows lazy writing?
Typically, producer and consumer threads exchange multiple buffer pointers on queues and so avoid sharing any single buffer. Given that this is a DLL and so memory-management calls can be problematic, I would probably avoid them as well by creating a pool of buffers at startup to transfer data round the system. I would use a buffer class rather than just pointers to memory, but it's not absolutely required, (just much more easy/flexible/safe).
Sleep() loops are a spectacularly bad way of communicating between threads. Sleep() does hae its uses, but this is not one of them. Delphi/Windows has plenty of synchronization mechanisms - events, semaphores, mutexes etc - tha make such polling unnecessary.
LU RD has also mentioned the problems of parallel processing of data whose order must be preserved. This often requires yet another thread, a list-style collection and sequence-numbers. I wouldn't try that until you have the inter-thread comms working well.
If you want to avoid the Sleep() call in your second thread, use a waitable timer like TSimpleEvent.
Set the sleep time to handle all your timing conditions.
There is an advantage of using this scheme instead of a normal Sleep(), since a waitable timer will not put the thread into a deep sleep.
To dispose the thread, see comments in code.
var
FEvent: TSimpleEvent;
FSleepTime: Integer = 100; // Short enough to handle all cases
Constructor TThread2.Create;
begin
Inherited Create( False);
FEvent := TSimpleEvent.Create;
Self.FreeOnTerminate := True;
end;
procedure TThread2.Execute;
var
DataCount: Integer;
begin
DataIdx1 := GetCurrentDataIdx;
while (fEvent.WaitFor(FSleepTime) = wrTimeout) do
begin
if Terminated then
break;
// Do your work
if (GetCurrentDataIdx - DataIdx1) >= DataCountToNotify then
begin
// Write data to buffer
DataIdx1 := GetCurrentIdx;
end;
end;
end;
// To stop the thread gracefully, call this instead of Terminate or override the DoTerminate
procedure TThread2.SetTerminateFlag;
begin
FEvent.SetEvent;
end;