Recent

Author Topic: Locked in a Loop Don't understand why  (Read 3410 times)

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Locked in a Loop Don't understand why
« on: May 26, 2019, 04:47:00 pm »
 Line 23:  I make the call to CountryRegion(MODE, Region,Country); passing three parms.
After one time thru it should return but it just continues to loop. Don't understand why.

Would someone look at this point out what I'm missing.

Willing to post code and a small data set on my GDrive.

Thanks





Code: Pascal  [Select][+][-]
  1.  procedure TForm1.btnRegionCountryClick(Sender: TObject);
  2.   Var I : Integer = -1;
  3.    Mode     : String = '';  {Valid  'O' 'B'}
  4.    Region   : String[2]  = '';
  5.    Country  : String[80] = '';
  6.    Indie    : String[1]  = '';
  7.    RCD      : String[80] = '';
  8.    LB5RCD   : String[40] = '';
  9.    NilCount : Integer = -1;
  10.   begin
  11.    {'[AG][Solomon Islands][I]'}
  12.        i := ListBox5.ItemIndex;
  13.        if i =-1 then begin exit; end;
  14.        LB5RCD := Listbox5.Items[i];
  15.  
  16.        ToTop(i,Listbox5);
  17.        RCD := GetRegionCountry(i);
  18.        Region   := ExtractWord(1,RCD,['[',']']);
  19.        Country  := ExtractWord(2,RCD,['[',']']);
  20.        Indie    := ExtractWord(3,RCD,['[',']']);
  21.        Mode     := 'B';
  22.        if Indie = 'O' then begin Mode := 'O' end;
  23.        CountryRegion(MODE, Region,Country);    //  <--- Makes the call
  24.        ListBox4.ItemIndex := 0;
  25.        ListBox4.Selected[i] := False;
  26.        ListBox3.ItemIndex := 0;
  27.        ListBox3.Selected[i] := False;
  28.        ListBox5.ItemIndex := 0;
  29.        ListBox5.Selected[i] := False;
  30.   end;
  31.  
  32.  {How it works:                                                                }
  33.  { Mode = 'B'  Both the Region field and Country field can be change based on  }
  34.  { the AREGION and/or ACOUNTRY.                                                }
  35.  { Mode = 'O' Only the Country field in the Record can be changed based on the }
  36.  { AREGION. The Region code in the record CAN NOT be changed as the country has}
  37.  { mutipual region codes.                                                      }
  38.  procedure TForm1.CountryRegion(AMODE : String; AREGION : String; ACOUNTRY : STRING);
  39.   Var i : Integer = -1;
  40.    BMode    : TChgMode;
  41.    Country  : String[45]  = '';
  42.    Region   : String[2]   = '';
  43.    City     : String[45]  = '';
  44.    LB4RCD   : String[180] = '';
  45.    NilCount : Integer = -1;
  46.    a : Integer = -1;
  47.    Begin
  48.     {[00F][8927][Broadus][US][K1][45.47314456][-105.46488607]}
  49.     {  TChgMode = (iRegion,  iCountry, iRegionCity, , iCityCountry)}
  50.     for i := 0 to Listbox4.Items.Count -1 do begin    //<-- enter the for loop
  51.         ListBox4.ItemIndex := i;
  52.         LB4RCD := Listbox4.Items[i];
  53.         Region  := ExtractWord(5,LB4RCD,['[',']']);
  54.         Country := ExtractWord(4,LB4RCD,['[',']']);
  55.         if (Region <> AREGION) And (Country <> ACOUNTRY) then begin Continue; end;
  56.         Edit8.Text := LB4RCD;
  57.         BMode := DetermineWhichNils(LB4RCD);
  58.         NilCount := CountWhat(ANIL, LB4RCD);
  59.  
  60.         if (BMODE = iZeroNils) OR  (BMODE = iAllThree)      then Continue
  61.         else if (NilCount = 1) And (BMODE = iCITY)          then  Continue
  62.         else if (NilCount = 2) And (BMODE = iRegionCountry) then Continue
  63.         else if (AMODE = 'O')  And (BMODE = iRegion)        then Continue;
  64.  
  65.         ListBox4.ItemIndex := i;
  66.         ToTop(i,Listbox4);
  67.         Application.ProcessMessages;
  68.  
  69.         { Region = 'AG'  AREGION = 'AG'     Country = ANIL   BMode = 'B'}
  70.         if (Region = AREGION) And (AMODE = 'B') then Begin
  71.            Edit4.Text := ACOUNTRY;
  72.            btnChgCountryClick(Nil);
  73.            Application.ProcessMessages;
  74.         end;
  75.  
  76.         { Region = 'ANIL'  AREGION = 'AG'     Country = 'a Country'   BMode = 'B'}
  77.         if (Country = ACOUNTRY) And (AMODE = 'B') then Begin
  78.             Edit5.Text := AREGION;
  79.             btnChgRegionClick(Nil);
  80.             Application.ProcessMessages;
  81.          end;
  82.     end; {end of for loop}                       //<--- Should exit after one time thru
  83.  end;  {end of procedure CountryRegion}
  84.  
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

ASerge

  • Hero Member
  • *****
  • Posts: 2494
Re: Locked in a Loop Don't understand why
« Reply #1 on: May 26, 2019, 05:06:05 pm »
What the ToTop function does?

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Locked in a Loop Don't understand why
« Reply #2 on: May 26, 2019, 05:20:15 pm »
Just sets focus and move the listbox item to the top of the box.
Rather than coding :

   Listbox1.ItemIndex := AIDX;
   Listbox1ABOX.TopIndex := -1 + ABOX.Items.Count;
   Listbox1ABOX.TopIndex := ABOX.ItemIndex;
   Listbox1ABOX.SetFocus;

everywhere I need it I can now code TOTOP(IDX,Listbox1);


Code: Pascal  [Select][+][-]
  1.  { How It Works:                                              }
  2.  { AIDX = the index of an item in a Listbox.                  }
  3.  { ABOX = Listbox   The item in the listbox will get focus and}
  4.  { and be displayed at the top of the listbox.                }
  5.  { if listbox3 or Listbox4 is passed as paramenters in ABOX   }
  6.  { then bot boxes will be displayed at the top.               }
  7.  procedure TForm1.ToTop(AIDX : Integer; ABOX : Tlistbox);
  8.   begin
  9.    if (ABOX = ListBox3) Or (ABOX = ListBox4) then begin
  10.       Listbox3.ItemIndex := AIDX;
  11.       Listbox3.TopIndex := -1 + Listbox3.Items.Count;
  12.       Listbox3.TopIndex := Listbox3.ItemIndex;
  13.       Listbox3.SetFocus;
  14.       Listbox4.ItemIndex := AIDX;
  15.       Listbox4.TopIndex := -1 + Listbox4.Items.Count;
  16.       Listbox4.TopIndex := Listbox4.ItemIndex;
  17.       Listbox4.SetFocus;
  18.       Exit;
  19.    end;
  20.    ABOX.ItemIndex := AIDX;
  21.    ABOX.TopIndex := -1 + ABOX.Items.Count;
  22.    ABOX.TopIndex := ABOX.ItemIndex;
  23.    ABOX.SetFocus;
  24.  end;
  25.                                                      
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

jamie

  • Hero Member
  • *****
  • Posts: 7707
Re: Locked in a Loop Don't understand why
« Reply #3 on: May 26, 2019, 05:21:05 pm »
I am going to take a guess here.

I know from your posting history you are using lots of ProcessMessages in your code and I see that you are also doing this
here too.

 It maybe a good idea to block the reentry of this procedure until finish..

 ether use a global variable to indicate this procedure is busy or use a local writable constant for that like I do.

 I guess you could also use a CriticalSection.

 Above your VAR declaration section..

 Const Busy :Boolean = False;

and at the start of your begin within this procedure.

Begin
  If Busy then Exit else Busy := True;

and at the end before the final exit..

Busy := False;
End;

 if you look at your code you are recalling the same buttonClick function so it gets reentered//

Try that.
« Last Edit: May 26, 2019, 05:31:57 pm by jamie »
The only true wisdom is knowing you know nothing

lucamar

  • Hero Member
  • *****
  • Posts: 4217
Re: Locked in a Loop Don't understand why
« Reply #4 on: May 26, 2019, 05:42:17 pm »
Above your VAR declaration section..

 Const Busy :Boolean = False;

and at the start of your begin within this procedure.

Begin
  If Busy then Exit else Busy := True;

and at the end before the final exit..

Busy := False;
End;

As a further enhancement, add a try..finally section to that code:
Code: Pascal  [Select][+][-]
  1. begin
  2.   if not Busy then
  3.   try
  4.     Busy := True;
  5.     {.. long process here...}
  6.   finally
  7.     Busy := False
  8.   end;
  9. end;

Otherwise an exception inside "long process" would leave that code unreachable from then on because Busy would be left True.

@JLWest: Don't over-use ProcessMessages; use it only when absolutely needed and taking extreme care of events interactions in your code.

It's easy to fall into loops with it, more so because there may be events shot from inside the LCL, for example when using size constraints, autosizing controls, BorderSpacing, etc.
« Last Edit: May 26, 2019, 05:48:53 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Locked in a Loop Don't understand why
« Reply #5 on: May 26, 2019, 06:00:40 pm »
OK.

Don't fully understand but I think you want me to declare a Const Busy : Boolean = False;
in the procedure where this is happening.

Before the loop I code: 'If Not Busy then Try Busy := True;'

Go into the for loop

And at the end before the exit of the procedure  'Finally Busy := False;'

Question: Yea, I do have 3 Application.ProcessMessages within the loop. Trying to get information to the screen.

Why not comment those out for a test.





FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Locked in a Loop Don't understand why
« Reply #6 on: May 26, 2019, 06:55:20 pm »
Commented out the three 'Application.ProcessMessages;'. It ran one time but I had the hour glass at the end it never came back.

Entered you suggested code. It still goes into an endless loop. The listbox has 34,621 items.

FPC can't handle it. Seems it would be a bug.

FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Locked in a Loop Don't understand why
« Reply #7 on: May 26, 2019, 07:12:12 pm »
Took out all the  Application.ProcessMessages; add the suggested code.

It stops with the hour glass and finally comes back. 

FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Locked in a Loop Don't understand why
« Reply #8 on: May 26, 2019, 07:18:10 pm »
Code: Pascal  [Select][+][-]
  1. if (Region <> AREGION) And (Country <> ACOUNTRY) then begin Continue; end;
Are you sure that is correct? This way it lets the code run even if 1 of them doesn't match, unless you change the "And" into "Or".

Also you are setting ItemIndex in multiple places, do you have onChange events or something in those listboxes? Because the events will run when you change, even while this loop is ongoing.

Then i don't know if these "btnChgCountryClick(Nil);" "btnChgRegionClick(Nil);" contain any conflicting code.

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Locked in a Loop Don't understand why
« Reply #9 on: May 26, 2019, 07:44:50 pm »
Attached is the entire program.

'if (Region <> AREGION) And (Country <> ACOUNTRY) then begin Continue; end;'

In other words if Region NOT = to AREGION AND Country Not = ACOUNTRY then it's not an item I want to process.

If I get a match on either one I want to process.

  'do you have onChange events or something in those listboxes?'

No the listbox's only contain strings. They all look like the following:

[AGAF][111418][Bila][Nil][AG][-09.19014776][160.95093948]
[01H][161210][Nil][Nil][Nil][39.64581208][-089.14446457]

The program is suppose to eliminate the Nil's with good data. The first record [AGAF] has a
code [AG] in the 5th position. From another listbox I can read AG and get the Solomon Islands.

"btnChgCountryClick(Nil);" "btnChgRegionClick(Nil);"
 
These procedures change the the fields in the strings and update the listbox line. In the case of the AGAF it will change :

[AGAF][111418][Bila][Nil][AG][-09.19014776][160.95093948]
                                      to
[AGAF][111418][Bila][Solomon Islands][AG][-09.19014776][160.95093948]


FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Locked in a Loop Don't understand why
« Reply #10 on: May 26, 2019, 08:07:02 pm »
There is 34,621 records or strings in the listbox.

If I cut them in half to 17,310 it runs perfect.

FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

jamie

  • Hero Member
  • *****
  • Posts: 7707
Re: Locked in a Loop Don't understand why
« Reply #11 on: May 26, 2019, 09:05:19 pm »
That's because there is a bug in the LISTBOX and other related controls due to the size limit not getting changed when
they stopped supporting WIn95/98/Me etc..

 The original limit is a size of a WORD size integer, which is 32767.
 
 All the functions that set/get lines directly in the listbox also has this limit.
 
 It has been recently looked at.. Maybe you can down load the Trunk and try it.

 Or for now,  you could use the direct API method to read a selection thus allowing you to use a much larger value.

 This also effects the Scrolling Range..

The only true wisdom is knowing you know nothing

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Locked in a Loop Don't understand why
« Reply #12 on: May 26, 2019, 09:16:58 pm »
Hi Jamie.


'It has been recently looked at.. Maybe you can down load the Trunk and try it.

 Or for now,  you could use the direct API method to read a selection thus allowing you to use a much larger value.'

Have no idea what that means.

Can you explain please.
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Locked in a Loop Don't understand why
« Reply #13 on: May 26, 2019, 09:29:36 pm »
A better solution would be to rethink the design of your program, and use a database specifically designed to handle multi-megabytes of string data (such as SQLite), rather than abusing listboxes to do this.

A listbox was conceived as a GUI container for strictly limited amounts of string data, in which it is possible to view all the strings on screen at once, or at least most of them with a limited amount of scrolling.

The LCL provides a good set of data-aware components you can use to browse data (in your case probably filtered via SQL) in chunks that are much more manageable for the user.
Using a database avoids the drawback of a GUI control like a listbox, which (by design) stuffs its entire data into memory at one time.

JLWest

  • Hero Member
  • *****
  • Posts: 1293
Re: Locked in a Loop Don't understand why
« Reply #14 on: May 26, 2019, 09:48:38 pm »
Your probably right howardpc. But I don't know SQL or how to implement it. Are there any examples?

A user dosn't need to see the data. The program ois just validaing fields.
FPC 3.2.0, Lazarus IDE v2.0.4
 Windows 10 Pro 32-GB
 Intel i7 770K CPU 4.2GHz 32702MB Ram
GeForce GTX 1080 Graphics - 8 Gig
4.1 TB

 

TinyPortal © 2005-2018