DarkDucke 2 Posted December 19, 2019 Hello, I need to create a task for each row of a TSgringGrid, this task will take content from a web page, and update the data in a cell. I tried as follows: procedure TForm1.BitBtn1Click(Sender: TObject); var I, nCount : Integer; begin I := 0; nCount := 0; for I := 1 to StringGrid.RowCount-1 do begin if StringGrid.Cells[0, I] <> 'done' then begin inc(Q); if Q > 5 then Break; Async( procedure begin Memo1.lines.add('I=' + I.ToString() + ' Q=' + Q.ToString()); GetWebContent(I); end ).Await( procedure begin Memo1.lines.add('Done I=' + I.ToString() + ' Q=' + Q.ToString()); end); end; end; end; But that doesn't work, the value of I is always the same, I can't get the position of the TStringGrid line. How can I do this? Create 5 out of 5 tasks until all Grid lines have been queried. This cannot freeze the user interface. Thanks!! Share this post Link to post
Lars Fosdal 1792 Posted December 19, 2019 Is it about the pitfalls of variable captures? The simplest solution to that is to simply divide and conquer. Also - the queuing code you wrote, will only do five scrapings since you never descrement nCount when a task completes, nor do you retry the loop until there are no lines not containing 'done'. procedure TForm1.QueueScraping(I, Q: Integer); Async( procedure begin Memo1.lines.add('I=' + I.ToString() + ' Q=' + Q.ToString()); GetWebContent(I); end ).Await( procedure begin Memo1.lines.add('Done I=' + I.ToString() + ' Q=' + Q.ToString()); end); end; procedure TForm1.BitBtn1Click(Sender: TObject); var I, nCount : Integer; begin I := 0; nCount := 0; for I := 1 to StringGrid.RowCount-1 do begin if StringGrid.Cells[0, I] <> 'done' then begin inc(nCount); if nCount > 5 then Break; QueueScraping(I, nCount) end; end; end; 2 Share this post Link to post
DarkDucke 2 Posted December 19, 2019 1 hour ago, Lars Fosdal said: Is it about the pitfalls of variable captures? The simplest solution to that is to simply divide and conquer. Also - the queuing code you wrote, will only do five scrapings since you never descrement nCount when a task completes, nor do you retry the loop until there are no lines not containing 'done'. procedure TForm1.QueueScraping(I, Q: Integer); Async( procedure begin Memo1.lines.add('I=' + I.ToString() + ' Q=' + Q.ToString()); GetWebContent(I); end ).Await( procedure begin Memo1.lines.add('Done I=' + I.ToString() + ' Q=' + Q.ToString()); end); end; procedure TForm1.BitBtn1Click(Sender: TObject); var I, nCount : Integer; begin I := 0; nCount := 0; for I := 1 to StringGrid.RowCount-1 do begin if StringGrid.Cells[0, I] <> 'done' then begin inc(nCount); if nCount > 5 then Break; QueueScraping(I, nCount) end; end; end; In fact, I forgot to report, this code is in a button, but stored in a timer that checks again every 5s Share this post Link to post
Lars Fosdal 1792 Posted December 19, 2019 Did the refactor solve your "always same I" problem? 1 Share this post Link to post
DarkDucke 2 Posted December 19, 2019 It worked perfectly, thanks for the help! 1 Share this post Link to post