0

The UI freezes during execution of my OTL multithreaded program. Tested with one to 16 thread, UI freezes immediately after procedure start.

  Parallel.ForEach(0, CalcList.Count-1)
  .NumTasks(nMax) 
  .NoWait
  .Execute(
   procedure(const value: integer)
   begin
     CalcUnit.EntrySearch(value);
    end)

All thread messages are correctly received by the OmniEventMonitor. When all threads are closed the OmniEventMonitor handles all the received messages at once. How can I determine what causes the freezing to find a resolution. Application.ProcessMessages and/or OmniTED.ProcessMessages in the OmnitEventMonitorTaskMessage does have no influence.

for a MCVE: on mainform:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Parallel.ForEach(0, 1)
  .Execute(
     procedure(const value: integer)
     begin
       CalcUnit.EntrySearch;
     end);
 end;

on the CalcUnit

procedure EntrySearch;
var
   I : integer ;
begin
  for I := 1 to 10 do begin
    MessageBeep(MB_ICONEXCLAMATION);
    Sleep(1000) ;
   end;
 end;

the MainForm freezes until the CalcUnit is completed.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Frits Molenkamp
  • 175
  • 1
  • 10
  • 1
    Why would you be calling `ProcessMessages`? Could we have an MCVE? – David Heffernan Nov 22 '14 at 20:57
  • @DavidHeffernan Thanks for your fast reply. Hoped to unfreeze the mainthread with ProcessMessages, (did not work) – Frits Molenkamp Nov 22 '14 at 21:28
  • 1
    The "hope to unfreeze" is sometimes referred to as "programming by accident". It's important to understand what `ProcessMessages` does when you use it. It's misuse can lead to a nightmare of subtle problems. .... As for why your UI is freezing? That will be due to something inside the `CalcUnit.EntrySearch` method (or something it calls etc.). – Disillusioned Nov 22 '14 at 21:45
  • 2
    In order to solve the problem you must first diagnose and understand it. That will take debugging of some sort. We cannot do that with no code. You need to either show code, an MCVE, or do the debugging yourself. – David Heffernan Nov 22 '14 at 22:29
  • @CraigYoung thank you for your comments, English is not my native language. I know what ProcessMessages does, been using Delphi since Delphi 4. Although New to Multithreading. The ProcessMessages I used to handle messages, via the OmniEventMonitor, from the threads to set a Progress Bar, (Didn't work). Inside the threads I did remove all connections to the MainForm but did not solve the freezing. – Frits Molenkamp Nov 23 '14 at 09:55
  • You should need ProcessMessages. We can't help until we have the detail. – David Heffernan Nov 23 '14 at 12:09
  • @DavidHeffernan Thanks you for your comments. I have removed everything out the CalcUnit.Entry until only the reading of a data file remained. Did move DataFiles to another location and did change the FileData format. AssignFile(qInputFile, Path); Reset(qInputFile); while Not eof(qInputFile) do begin with qWallRec Do begin Read (qInputFile, qWallRec); {reading the lines and the contents into an array} end; {With qWallRec} end; this file readings is done about 350 times. Nothing changed the Freezing. I don't know what to do anymore. – Frits Molenkamp Nov 24 '14 at 09:31
  • I don't know either. You've got more hope than I do though because you can see the code. So, good luck with your efforts to work it out. – David Heffernan Nov 24 '14 at 09:43
  • @DavidHeffernan Sorry for the lack of an MCVE, tried to make one for my CPU usage problem, but failed. Now I could make a MCVE for the Freezing problem. What can I do with the MCVE? do I attach a zip file somewhere or can I post the code somewhere? Thanks Frits – Frits Molenkamp Nov 24 '14 at 11:12
  • Post the code in the question. It needs to be simple enough to do that. So you'll need to cut it down to a bare minimum. – David Heffernan Nov 24 '14 at 11:21
  • In your updated question, the `.NoWait` is not included. This means (I think) that the `Button1Click` method is waiting until the parallel task is completed == GUI freeze. – LU RD Nov 24 '14 at 11:48
  • But there is more to this, see [Why is OmniThreadLibrary's ForEach blocking main thread?](http://stackoverflow.com/q/16880457/576719). – LU RD Nov 24 '14 at 12:03
  • @LURD Thank for your comments. The NoWait makes no difference, In my original code the NoWait is used and MainForm freezes, I will study your link, Thanks again – Frits Molenkamp Nov 24 '14 at 19:43
  • @LURD with your link I could make my main thread not Freeze anymore, however one thread will not close, so program will not close. Thanks again. – Frits Molenkamp Nov 24 '14 at 21:46
  • Sorry I could not help more. OTL is not in my toolbox, since I use my own multithreading framework. – LU RD Nov 24 '14 at 22:11
  • It's obvious why the code in the question blocks the main thread. The ForEach blocks until it completes. – David Heffernan Nov 25 '14 at 08:15
  • @DavidHeffernan thanks, Yes David you are right. shall I delete or end my question? – Frits Molenkamp Nov 25 '14 at 09:57
  • You could perhaps add an answer and that would get it done. Now that you've edited the question it is a decent question. – David Heffernan Nov 25 '14 at 10:05

1 Answers1

0

The Application UI freezes because it is waiting for all threads have been completed. I had to destroy the ForEach interface at task Completion. Used the OnStop method in the MainForm to destroy the last Thread. Look at: Incrementing Progress Bar from a ForEach Loop

{Private declarations}
FWorker : IOmniParallelLoop<integer>;

FWorker := Parallel.ForEach(0, CalcList.Count-1)
.TaskConfig(Parallel.TaskConfig.OnMessage(Self))
.NumTasks(nMax) 
.NoWait
.OnStop(procedure (const task: IOmniTask)
  begin
  task.Invoke(procedure begin
      FWorker := nil;
    end);
  end);

FWorker
.Execute(
  procedure (const value: integer)
  begin
     CalcUnit.EntrySearch(value);
  end);
Frits Molenkamp
  • 175
  • 1
  • 10