2012-03-01 13 views
9

私は、ユーザーがGoogle Mapsを使用できるようにするシステムをdelphiで構築しようとしています。すべて正常に動作しますが、新しいTWebBrowserオブジェクトが作成され、Google Mapsを処理するjavascriptがロードされるたびに、新しいスレッドが多数生成されていることに気づいています。Delphi TWebBrowserのJavaScript、スレッドを閉じる

私の問題は、Webブラウザが破棄されても(そして、確実に破棄されても)作成されたスレッドが残っているということです。私はこのプログラムを長時間実行するように設計しており、Googleマップの開閉は何度も起こるため、しばらくすると非常に多くのスレッドが生成され、終了せずにプログラムが大幅に減速します。

これらのスレッドを自分自身で破棄する方法はありますか、スレッドを持続させる原因となっている何かが間違っていますか?

私は、次のコードのオフに私のプログラムを基づかています:空白:

const 
HTMLStr: AnsiString = 
'<html> '+  
'<head> '+ 
'<meta name="viewport" content="initial-scale=1.0, user-scalable=yes" /> '+ 
'<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true">  </script> '+ 
'<script type="text/javascript"> '+ 
''+ 
''+ 
' var geocoder; '+ 
' var map; '+ 
' var trafficLayer;'+ 
' var bikeLayer;'+ 
' var markersArray = [];'+ 
''+ 
''+ 
' function initialize() { '+ 
' geocoder = new google.maps.Geocoder();'+ 
' var latlng = new google.maps.LatLng(40.714776,-74.019213); '+ 
' var myOptions = { '+ 
'  zoom: 13, '+ 
'  center: latlng, '+ 
'  mapTypeId: google.maps.MapTypeId.ROADMAP '+ 
' }; '+ 
' map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); '+ 
' trafficLayer = new google.maps.TrafficLayer();'+ 
' bikeLayer = new google.maps.BicyclingLayer();'+ 
' map.set("streetViewControl", false);'+ 
' } '+ 
''+ 
''+ 
' function codeAddress(address) { '+ 
' if (geocoder) {'+ 
'  geocoder.geocode({ address: address}, function(results, status) { '+ 
'  if (status == google.maps.GeocoderStatus.OK) {'+ 
'   map.setCenter(results[0].geometry.location);'+ 
'   PutMarker(results[0].geometry.location.lat(),  results[0].geometry.location.lng(),  results[0].geometry.location.lat()+","+results[0].geometry.location.lng());'+ 
'  } else {'+ 
'   alert("Geocode was not successful for the following reason: " + status);'+ 
'  }'+ 
'  });'+ 
' }'+ 
' }'+ 
''+ 
''+ 
' function GotoLatLng(Lat, Lang) { '+ 
' var latlng = new google.maps.LatLng(Lat,Lang);'+ 
' map.setCenter(latlng);'+ 
' PutMarker(Lat, Lang, Lat+","+Lang);'+ 
' }'+ 
''+ 
''+ 
'function ClearMarkers() { '+ 
' if (markersArray) {  '+ 
' for (i in markersArray) { '+ 
'  markersArray[i].setMap(null); '+ 
' } '+ 
' } '+ 
'} '+ 
''+ 
' function PutMarker(Lat, Lang, Msg) { '+ 
' var latlng = new google.maps.LatLng(Lat,Lang);'+ 
' var marker = new google.maps.Marker({'+ 
'  position: latlng, '+ 
'  map: map,'+ 
'  title: Msg+" ("+Lat+","+Lang+")"'+ 
' });'+ 
' markersArray.push(marker); '+ 
' }'+ 
''+ 
''+ 
' function TrafficOn() { trafficLayer.setMap(map); }'+ 
''+ 
' function TrafficOff() { trafficLayer.setMap(null); }'+ 
''+''+ 
' function BicyclingOn() { bikeLayer.setMap(map); }'+ 
''+ 
' function BicyclingOff(){ bikeLayer.setMap(null);}'+ 
''+ 
' function StreetViewOn() { map.set("streetViewControl", true); }'+ 
''+ 
' function StreetViewOff() { map.set("streetViewControl", false); }'+ 
''+ 
''+'</script> '+ 
'</head> '+ 
'<body onload="initialize()"> '+ 
' <div id="map_canvas" style="width:100%; height:100%"></div> '+ 
'</body> '+ 
'</html> '; 


procedure TfrmMain.FormCreate(Sender: TObject); 
var 
    aStream  : TMemoryStream; 
begin 
    WebBrowser1.Navigate('about:blank'); 
    if Assigned(WebBrowser1.Document) then 
    begin 
     aStream := TMemoryStream.Create; 
     try 
    aStream.WriteBuffer(Pointer(HTMLStr)^, Length(HTMLStr)); 
    //aStream.Write(HTMLStr[1], Length(HTMLStr)); 
    aStream.Seek(0, soFromBeginning); 
    (WebBrowser1.Document as IPersistStreamInit).Load(TStreamAdapter.Create(aStream)); 
    finally 
    aStream.Free; 
    end; 
    HTMLWindow2 := (WebBrowser1.Document as IHTMLDocument2).parentWindow; 

end; 
end; 


procedure TfrmMain.ButtonGotoLocationClick(Sender: TObject); 
begin 
    HTMLWindow2.execScript(Format('GotoLatLng(%s,%s)',[Latitude.Text,Longitude.Text]),   'JavaScript'); 
end; 

procedure TfrmMain.ButtonClearMarkersClick(Sender: TObject); 
begin 
    HTMLWindow2.execScript('ClearMarkers()', 'JavaScript') 
end; 

procedure TfrmMain.ButtonGotoAddressClick(Sender: TObject); 
var 
    address : string; 
begin 
    address := MemoAddress.Lines.Text; 
    address := StringReplace(StringReplace(Trim(address), #13, ' ', [rfReplaceAll]), #10, ' ' , [rfReplaceAll]); 
    HTMLWindow2.execScript(Format('codeAddress(%s)',[QuotedStr(address)]),  'JavaScript'); 
end; 

procedure TfrmMain.CheckBoxStreeViewClick(Sender: TObject); 
begin 
    if CheckBoxStreeView.Checked then 
    HTMLWindow2.execScript('StreetViewOn()', 'JavaScript') 
    else 
    HTMLWindow2.execScript('StreetViewOff()', 'JavaScript'); 

end; 

procedure TfrmMain.CheckBoxBicyclingClick(Sender: TObject); 
begin 
    if CheckBoxBicycling.Checked then 
    HTMLWindow2.execScript('BicyclingOn()', 'JavaScript') 
    else 
    HTMLWindow2.execScript('BicyclingOff()', 'JavaScript'); 
end; 


procedure TfrmMain.CheckBoxTrafficClick(Sender: TObject); 
begin 
    if CheckBoxTraffic.Checked then 
    HTMLWindow2.execScript('TrafficOn()', 'JavaScript') 
    else 
    HTMLWindow2.execScript('TrafficOff()', 'JavaScript'); 
end; 


end. 

プログラムを約に移動するHTMLWindowを設定し、基本的なデストラクタを使用しています。 ありがとうございます。

+0

どこでどのようにWebブラウザを破壊しますか? – GolezTrol

+0

Webブラウザは、親TFormによって処理されるTFormの上に置かれます。子TFormを破棄し、次のデストラクタコードを使用します。 'destructor TGoogleMap.Destroy; begin HTMLWindow2.navigate( 'about:blank'); HTMLWindow2:= nil; WebBrowser1.DestroyComponents; WebBrowser1.Destroy; 継承 end; ' – user1242937

+4

開始のために、あなたの' destructor'は全く必要ありません。そこには大きなサラダがあります。オーナーフォームは 'TWebBrowser'自体を解放します。 – kobik

答えて

2

これはこの問題には答えません。シミュレーションする問題が単純化されます。

各ボタンをクリックした後に実行されているスレッドの数を確認します。それはSimple Google Maps exampleを使用しているので、問題はJavaScriptの部分でさえありません。

Unit1は -

unit Unit2; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls, OleCtrls, SHDocVw, ActiveX; 

type 
    TForm2 = class(TForm) 
    WebBrowser1: TWebBrowser; 
    procedure FormCreate(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form2: TForm2; 

implementation 

{$R *.dfm} 

const 
    HTMLString: AnsiString = 
    '<!DOCTYPE html>' + 
    '<html>' + 
    ' <head>' + 
    ' <title>Google Maps JavaScript API v3 Example: Map Simple</title>' + 
    ' <meta name="viewport"' + 
    '  content="width=device-width, initial-scale=1.0, user-scalable=no">' + 
    ' <meta charset="UTF-8">' + 
    ' <style type="text/css">' + 
    '  html, body, #map_canvas {' + 
    '  margin: 0;' + 
    '  padding: 0;' + 
    '  height: 100%;' + 
    '  }' + 
    ' </style>' + 
    ' <script type="text/javascript"' + 
    '  src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>' + 
    ' <script type="text/javascript">' + 
    '  var map;' + 
    '  function initialize() {' + 
    '  var myOptions = {' + 
    '   zoom: 8,' + 
    '   center: new google.maps.LatLng(-34.397, 150.644),' + 
    '   mapTypeId: google.maps.MapTypeId.ROADMAP' + 
    '  };' + 
    '  map = new google.maps.Map(document.getElementById(''map_canvas''),' + 
    '   myOptions);' + 
    '  }' + 
    '  google.maps.event.addDomListener(window, ''load'', initialize);' + 
    ' </script>' + 
    ' </head>' + 
    ' <body>' + 
    ' <div id="map_canvas"></div>' + 
    ' </body>' + 
    '</html>'; 

procedure TForm2.FormCreate(Sender: TObject); 
var 
    HTMLStream: TMemoryStream; 
begin 
    WebBrowser1.Navigate('about:blank'); 
    if Assigned(WebBrowser1.Document) then 
    begin 
    HTMLStream := TMemoryStream.Create; 
    try 
     HTMLStream.WriteBuffer(Pointer(HTMLString)^, Length(HTMLString)); 
     HTMLStream.Seek(0, soFromBeginning); 
     (WebBrowser1.Document as IPersistStreamInit).Load(TStreamAdapter.Create(HTMLStream)); 
    finally 
     HTMLStream.Free; 
    end; 
    end; 
end; 

end. 
をそれにTWebBrowserとフォームが含まれており、フォームのOnCreateイベントのイベントハンドラ - OnClickイベントハンドラを持つだけでボタン

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls, PsAPI, TlHelp32, Unit2; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

function GetThreadCount(const APID: Cardinal): Integer; 
var 
    NextProc: Boolean; 
    ProcHandle: THandle; 
    ThreadEntry: TThreadEntry32; 
begin 
    Result := 0; 
    ProcHandle := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 
    if (ProcHandle <> INVALID_HANDLE_VALUE) then 
    try 
    ThreadEntry.dwSize := SizeOf(ThreadEntry); 
    NextProc := Thread32First(ProcHandle, ThreadEntry); 
    while NextProc do 
    begin 
     if ThreadEntry.th32OwnerProcessID = APID then 
     Inc(Result); 
     NextProc := Thread32Next(ProcHandle, ThreadEntry); 
    end; 
    finally 
    CloseHandle(ProcHandle); 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    ModalForm: TForm2; 
begin 
    ModalForm := TForm2.Create(nil); 
    try 
    ModalForm.ShowModal; 
    finally 
    ModalForm.Free; 
    end; 
    ShowMessage('Thread count: ' + 
    IntToStr(GetThreadCount(GetCurrentProcessId))); 
end; 

end. 

Unit2のあるメインフォームを、含まれています

+0

問題はGoogleマップのサイトに関連していますか、またはTWebBrowserのリークを読み込んだページに問題がありますか? – EMBarbosa

+1

@EMBarbosa、それはいくつかのページで起こりますが、すべてではありません。 GoogleMapsだけでなく、 – TLama

関連する問題