21

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.

Community
  • 1
  • 1
Roland Bengtsson
  • 5,058
  • 9
  • 58
  • 99
  • 3
    Are you sure which the GUI frezees while the map is loaded? because The TWebBrowser acts asynchronously. can you show the code which you are using to load the map? – RRUZ Mar 01 '12 at 22:25
  • Have you tried it with TEmbeddedWB from www.bsalsa.com? It might have a solution already, and be pretty easy to switch to it and get async loads working. – Warren P Mar 30 '12 at 15:55
  • Thanks for the suggestions both RRUZ and WarrenP. RRUZ are right that it is already async loading in TWebBrowser. So in my case the reason is something else. I have to investigate because the code is rather complex... – Roland Bengtsson Mar 31 '12 at 18:44

1 Answers1

3

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!

E.F. Nijboer
  • 176
  • 5