2011-05-08 3 views
3

편집 는이 1 개 라인을 좁혀 시간을 소비 응용 프로그램 잠금 TWebbrowsers의 HTML을 액세스하는 동안

HTML := wb.OleObject.Document.documentElement.innerHTML; 

... 어떻게 속도를 위로 할 수 있는가?

다음 코드를 사용하면 내 응용 프로그램이 페이지의 HTML (Delphi XE)에 액세스하는 동안 1-2 초 동안 응답하지 않을 수 있습니다.

function Button1Click(Sender : TObject); 
begin 
    wb.navigate('http://10.0.0.154/stats'); 
    // Use a timer to poll the page - dont wait and process app messages 
    timer1.enabled := true; 
end; 

procedure Timer1Timer(Sender : TObject); 
var 
    HTML : WideString; 
begin 
    If GetHTML(HTML) = true then 
    begin 
     Timer1.enabled := false; 
     { do something } 
    end; 
end; 


function GetHTML(var HTML : WideString) : boolean; 
var 
    Document : IHTMLDocument2; 
begin 
    HTML := ''; 
    Result := false; 

    Document := wb.DOcument as IHTMLDocument2; 
    If Assigned(Document) then 
    begin 
    try 
     HTML := wb.OleObject.Document.documentElement.innerHTML; 
     Result := true; 
    except 
     Result := false; 
    end; 
    end; 
end; 

그러나 내 GetHTML 메서드에서 뭔가를 반환하는 데 1-2 초가 걸리고 UI가 잠길 수 있습니다. Delphi XE로 AQTime을 보면 메서드 호출이 느리다는 것입니다 (1-2 초). Sporatic이고 페이지가 아직 중간로드 일 때 실패할지 궁금합니다.

내가로드중인 페이지는 자바 스크립트와 500k로 가득한 사내 페이지입니다. ReadyState가 계속 실행되는 경우에도 페이지가 준비되기 전에 실행되므로 OnDocumentComplete를 사용할 수 없습니다. 일찍.

TWebbrowser의 HTML에 액세스 할 수있는 사람이라면 누구나 쉽게 읽을 수 있습니다.

+0

wb.Navigate은 즉시 반환을,이 응용 프로그램 매달려의 원인이되지 않도록. TWebBrowser는 페이지를 다운로드 한 다음 표시를 위해 렌더링해야합니다. 즉, HTML 가져 오기 지연이 발생합니다.원시 HTML 만 원하면 Indy, ICS 또는 TDownLoadURL (표준 작업)을 사용하지 않는 이유는 무엇입니까? – crefird

+0

나는 HTML 처리가 끝나면 HTML 처리가 끝난다. 자바 스크립트는 인디, ICS 등 이후 TWebbrowser를 사용해야하는 이유이기도하다. 자바 스크립트를 실행하지 않을 것이다. – Wizzard

+0

'innerHtml' 대신'outerHtml'을 사용하려고 했습니까? 어쩌면 그것이 효과를 낼 것입니다. 또한 TWebBrowser 컨트롤을 호스팅하는 경우 FEATURE_BROWSER_EMULATION을 사용하여 TWebBrowser가 최신 버전을 표시하도록합니다 (이 시점에서 9 번, 호스팅 된 컨트롤의 기본 모드는 7 번). 아마도 내가 테스트하지는 않았지만 아마도 속도 이점이있을 것입니다. –

답변

2

문제는 HTML을 가져 오기 전에 TWebBrowser가 페이지 로딩을 완료하지 못하게하는 것입니다. 이것은 wb.Navigate를 호출하는 코드와 InnerHTML을 가져 오는 예외를 처리해야하는 방법을 보여주지 않기 때문에 추측 일뿐입니다.

다음과 같은 시도해야합니다, 나는 브라우저가 작업을 완료하기 전에 innerHTML을 액세스를 시도하는 것으로 의심되는 @의 crefird의 답변과 마찬가지로

procedure TForm1.GetHTML(URL: string; var HTML: string); 
begin 
    wb.Navigate(URL); 
    Application.ProcessMessages; 
    while wb.Busy do 
    Application.ProcessMessages; 
    HTML := wb.OleObject.Document.documentElement.innerHTML; 
end; 
+0

감사합니다. 예제를 업데이트했습니다. 나는 .Busy와 .ReadyState를 사용하여 페이지가 준비되지 않았을지라도 true/complete를 반환한다는 것을 발견했다. – Wizzard

+0

@Wizzard - .Busy는 TWebBrowser가 페이지 로딩을 완료하고 .Busy가 False로 변경 될 때까지 True를 반환합니다. TWebBrowser는 JavaScript로 인해 작업을 계속할 수 있지만 HTML이로드되었습니다. – crefird

+0

wb.Busy로 Busy 상태를 읽는 것은 잠시 동안 전체 어플리케이션을 차단하는 경우가 있습니다. wb.Busy가 간단한 깃발이 아닌 것 같습니다. –

0

...

READSTATE/없음의 경우

1) "FBrowserBusy : Boolean"과 같이 전역 변수 또는 양식의 비공개 멤버를 만듭니다 (FOR NOT INGET). 예를 들어, 다음과 같은 방법으로 TWebBrowser의 상태를 정확하게 나타낼 수 있습니다. CAL을 수행하기 전에 TRUE로 초기화하려면 Ling ".Navigate") 2) @crefird가 그의 대답에서 보여 주듯이 "while"루프를 사용하고 "FBrowserBusy"대신 "wb.Busy"를 사용하십시오. 3) TWebBrowser 인스턴스에 OnDocumentComplete 이벤트를 추가하고이 이벤트를 FBusy : = False로 설정합니다.

이렇게하면 충돌을 제거하고 외부 루틴에서 심문하기 전에 TWebBrowser 객체가 문서로드를 완료했는지 확인합니다.

희망이 있으면 도움이 될 것입니다.

4

OnDocumentComplete는 페이지를 탐색 할 때 여러 번 (프레임) 실행될 수 있습니다.

어떻게 제대로 OnDocumentComplete을 구현 :

procedure YourForm.OnDocumentComplete(
    Sender: TObject; 
    const pDisp: IDispatch; 
    var URL: OleVariant); 
var 
    currentBrowser: IWebBrowser; 
    topBrowser: IWebBrowser; 
    document: OleVariant; 
    windowName: string; 
begin 
    currentBrowser := pDisp as IWebBrowser; 
    topBrowser := (Sender as TWebBrowser).DefaultInterface; 
    if currentBrowser = topBrowser then 
    ShowMessage('Complete document was loaded') 
    else 
    begin 
    document := currentBrowser.Document; 
    windowName := document.ParentWindow.Name; 
    ShowMessage(Format('Frame "%s" was loaded', [windowName])); 
    end; 
end; 

소스 :

http://www.cryer.co.uk/brian/delphi/twebbrowser/twebbrowser_events.htm#OnDocumentComplete

관련 문제