Good time of the day, forum users.

I just read about the threads, so I solved the problem: there is a list of files (in stringGrid ), each file is processed (very long) by a certain algorithm.

The code is like a worker, just, maybe, something overlooked. Look, please: I decided to create 2 streams (1st for file enumeration, 2nd for processing each file).

 type T_ListFiles = class(TThread) private PrProgress3: integer; procedure SetProgress3; protected procedure Execute; override; end; type T_ProcCalculate = class(TThread) private PrProgress4: integer; procedure SetProgress4; protected procedure Execute; override; end; PrSemaphore3: THandle; PrThLF: T_ListFiles; PrThPC: T_ProcCalculate; //begin T_Thread1--------------------------------------------------------------- procedure T_ListFiles.Execute; {перебор файлов, кол-во = 3шт.} var i: integer; begin for i := 1 to 3 do begin PrProgress3 := i; Synchronize(SetProgress3); if PrThLF.Terminated then begin PrThLF.Free; exit; end; PrThPC := T_ProcCalculate.Create(false); WaitForSingleObject(PrSemaphore3, infinite); end; CloseHandle(PrSemaphore3); PrThLF.Free; PrThPC.Free; end; procedure T_ListFiles.SetProgress3; begin Form1.Label6.Caption := IntToStr(PrProgress3); end; //end T_Thread1----------------------------------------------------------------- //begin T_Thread2--------------------------------------------------------------- procedure T_ProcCalculate.Execute; {обработка файла} var i: integer; begin for i := 0 to 100 do begin PrProgress4 := i; sleep(100); if PrThPC.Terminated then begin PrThPC.Free; exit; end; Synchronize(SetProgress4); end; ReleaseSemaphore(PrSemaphore3, 1, nil); end; procedure T_ProcCalculate.SetProgress4; begin Form1.Gauge2.Progress := PrProgress4; end; //end T_Thread2----------------------------------------------------------------- procedure TForm1.FormCreate(Sender: TObject); begin PrSemaphore3 := CreateSemaphore(nil, 0, 1, nil); end; procedure TForm1.StartClick(Sender: TObject); begin PrThLF := T_ListFiles.Create(false); end; procedure TForm1.abortClick(Sender: TObject); begin PrThPC.Terminate; PrThLF.Terminate; end; 

Thanks in advance.

Update

I agree, I have bent over multithreading (although it was probably possible to split the list of files into about 10 streams and significantly reduce the total processing time).
But without a few threads in my application, I will not get along, for the one reason that the application "hangs" during the processing of the file.

  Но все равно вопрос остается: я все правильно написал? 
  • Yes, I use threads, solely so as not to freeze the interface.
  • Since I was just so close to the threads, I decided to look at the relationship between them + the semaphore work (if it doesn’t slow down the work, then I’ll leave it for now)
  • I drove CloseHandle several times, until I saw it, but I still did not drive the program
  • And here it is possible in more detail , about the logic of creation / decrement of the counter / release of the semaphore, what exactly is wrong?
  • And another question: I understand correctly, that the flow doesn’t care which semaphore to use - it uses the first one it gets (that is, the stream does not bind to the semaphore and vice versa)?
  • 2
    Not entirely clear, what does multithreading do? Your threads are running one after another. Strictly. - Yura Ivanov
  • @Yura Ivanov, I agree. The task itself is not for multithreading. Dear @ Konstantin78 should understand yourself, an approximate range of tasks where multithreading is expedient and necessary. In particular, to control the interface during the "infinite" cycle (removal of experimental data), etc. - BuilderC
  • Updated the question - Konstantin78

1 answer 1

If you solve the problem of parallel processing of one hundred files, then it is incorrect. If you use threads solely in order not to freeze the interface, then one stream is enough.
Threat Semaphore is not needed here. To wait for the thread to finish, there is a TThread.WaitFor, which internally uses the already existing Handle of the thread. You have a logic for creating / decrementing a counter / releasing a semaphore that is not entirely correct. When restarting, for example, CloseHandle will give an invalid handle. And there are not enough checks.

UPD

I initially pointed out that the task is either not formulated, or the task is not described. As for the functionality implemented in the question, such code will be enough:

 procedure T_ListFiles.Execute; var i: integer; begin for i := 1 to 3 do begin FProgress3 := i; Synchronize(SetProgress3); for j:=1 to 100 do begin FProgress4 := j; Synchronize(SetProgress4); if Terminated then break; Sleep(100); end; end; end; ... procedure TForm1.abortClick(Sender: TObject); begin PrThLF.Terminate; end; 

and the rest is gently rubbed.

Further options are possible:

  • make the first loop in the GUI and start three threads, wait for them to be executed, catching the end, for example in TThread.OnTerminate ...
  • get in gui a list of 300 (3 to 100) files and run 300 threads (in a pool of five threads simultaneously)
  • ...

Running child threads from a thread launched from gui, i.e. the third level is an extra complication of logic. Everything is fine unfolding in a simple list, tree - excessive complexity. KISS !

As for the semaphore, I don’t think that it’s appropriate to describe what it is for and how to work with it, as it’s in the internet full of descriptions and examples. Say, this is an additional task, the code in question has nothing to do. "Let it remain"? - well, let it work, after all ... A semaphore could be used in the implementation of, for example, a thread pool ... in the future.

Regarding CloseHandle . Honestly, I never had the desire to check what would happen if the “created-delete” principle is violated, an exception may be generated and it may just be returned to INVALID_HANDLE , everything is written in the docks, I would be at the Windows site open;close;close;...close; swore, then it may work, but carelessly and unpredictably (looking from the side at the code).

Threat There are implementations of the pool , you can see in them how the pool is implemented, I admit that they use semaphores there ...

  • one
    @ Konstantin78, updated the answer. - Yura Ivanov