@H_301_1@我试图在delphi中构建一个允许用户使用谷歌地图的系统.一切正常,但我注意到每次创建一个新的TWebBrowser对象并加载处理谷歌地图的javascript时,会生成许多新的线程.
我的问题是,即使一旦web浏览器被破坏(并且它被明确地销毁),创建的线程仍然存在.我正在设计这个程序有很长的运行时间和谷歌地图的打开和关闭发生多次,因此,一段时间后,生成了很多线程,并没有终止该程序显着减慢.
有没有办法自己销毁这些线程,或者我做错了导致线程持续存在?
我的程序基于以下代码:
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,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.@H_403_9@程序使用一个基本的析构函数来设置HTMLWindow导航到about:blank.
提前致谢
解决方法
这不回答这个问题,它只是简化了要模拟的问题.
查看每次单击按钮后运行的线程数.它使用Simple Google Maps example
,所以问题甚至不在你的javascript部分.
Unit1 – 包含主窗体,其中只是一个带有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.@H_403_9@Unit2 – 包含带有TWebBrowser的表单和表单的OnCreate事件处理程序
unit Unit2; interface uses Windows,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.@H_403_9@