Jump to content
DarkDucke

Create multiple tasks without freezing the interface

Recommended Posts

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

 

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;

 

  • Thanks 2

Share this post


Link to post
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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×