Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update TWebBrowser in a separate thread?

I use a TWebBrowser to show a Google map. The problem is that it blocks the main ui thread while it loads the map. Is it possible to update the map in a separate thread?

Edit: RRUZ you are right TWebBrowser have async loading for the URL. But I found the problem why it blocks The call:

if WaitWhileProcessing and (MapQueryResult.Count > 0) then 
  Result := MapQueryResult[0] as TMapQuery;

and the method:

function TMapItemCollection.WaitWhileProcessing: Boolean;
var
  vMaxSleepCnt: Integer;
begin
  Result := True;
  vMaxSleepCnt := 0;
  while Processing or Loading do
  begin
    inc(vMaxSleepCnt);
    Application.ProcessMessages;
    Sleep(100);
    if vMaxSleepCnt = 100 then
    begin
      Result := False;
      Break;
    end;
  end;
end;

So it seems to fix this the code should be refactored. But this is not the scope for this question.

like image 776
Roland Bengtsson Avatar asked Mar 01 '12 22:03

Roland Bengtsson


1 Answers

When the if statement is executed and calls WaitWhileProcessing to evaluate the condition, it loops a 100 times with a 10th of a second sleep. But what messages are waiting when calling ProcessMessages? Could the method be called again recursively? It will never get to the sleep but keeps invoking this method. By the way, be aware that ProcessMessages is really bad practice, but for now... try this:

var
  isWaitWhileProcessingBusy :boolean = false;

function TMapItemCollection.WaitWhileProcessing: Boolean;
var
 vSleepCnt: Integer;
begin      
  if not isWaitWhileProcessingBusy then
  begin
    isWaitWhileProcessingBusy = true;
    vSleepCnt := 0;
    while Processing or Loading or vSleepCnt < 100 do
    begin
      inc(vSleepCnt);
      Application.ProcessMessages;
      Sleep(100);
    end;
    isWaitWhileProcessingBusy := false;
  end;
  Result = Processing or Loading;
end;

As you can see I also changed some other minor things. The break is not in the while condition and the result is simply the result of Processing or Loading (because that expression gives the actual result). The extra isWaitWhileProcessingBusy outside of the function keeps the message loop from re-entering. Hopefully that will prevent locking up the user interface. This also isn't best practice but for now it just might help to resolve and with it pinpoint the problem.

Is there a reason why you poll Loading/Processing? Wouldn't it be much easier to use the OnDocumentComplete event of TWebBrowser?

... and another thought crossed my mind... Have you checked the task manager? google maps is using flash, an activex component also using the main UI Thread. This could also be the resource hog causing starvation.

Good luck!

like image 162
E.F. Nijboer Avatar answered Oct 08 '22 12:10

E.F. Nijboer