21

TWebBrowser を使用して Google マップを表示します。問題は、マップの読み込み中にメインの ui スレッドがブロックされることです。別のスレッドでマップを更新することは可能ですか?

編集: RRUZあなたの言う通り TWebBrowser には URL の非同期読み込みがあります。しかし、なぜそれが呼び出しをブロックするのかという問題を見つけました:

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

そして方法:

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;

したがって、コードをリファクタリングする必要があるため、これを修正するようです。しかし、これはこの質問の範囲ではありません。

4

1 に答える 1

3

if ステートメントが実行され、WaitWhileProcessing を呼び出して条件を評価すると、10 分の 1 秒のスリープで 100 回ループします。しかし、ProcessMessages を呼び出すと、どのようなメッセージが待機しているのでしょうか? メソッドを再帰的に再度呼び出すことはできますか? スリープ状態になることはありませんが、このメソッドを呼び出し続けます。ところで、ProcessMessages は本当に悪い習慣であることに注意してください。

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;

ご覧のとおり、他にもいくつかの小さな変更を加えました。ブレークは while 条件ではなく、結果は単に処理または読み込みの結果です (その式が実際の結果を与えるため)。関数の外側に追加の isWaitWhileProcessingBusy を使用すると、メッセージ ループが再入力されなくなります。うまくいけば、ユーザー インターフェイスがロックされるのを防ぐことができます。これもベストプラクティスではありませんが、今のところ、問題を解決して特定するのに役立つかもしれません。

Loading/Processing をポーリングする理由はありますか? TWebBrowser の OnDocumentComplete イベントを使用する方がはるかに簡単ではないでしょうか。

...そして、別の考えが頭をよぎりました... タスクマネージャーを確認しましたか? Google マップは、メインの UI スレッドも使用する ActiveX コンポーネントであるフラッシュを使用しています。これは、飢餓の原因となるリソースの浪費になる可能性もあります。

幸運を!

于 2012-04-27T14:07:47.683 に答える