2011-12-28 79 views
2

這裏是我的代碼:的XMLHTTPRequest異步使用輪詢readyState的

var 
    xhttp: OleVariant; 

xhttp := CreateOleObject('MSXML2.XMLHTTP'); 
xhttp.Open('GET', URL, True); 
xhttp.send(); 

while xhttp.readyState <> 4 do 
begin 
    Application.HandleMessage;   
end; 

// status property is available only when readyState is complete 
if (xhttp.Status = 200) then... 
// do something 

在這種情況下,我不想使用事件onreadystatechange

問題: 是否安全的readyState輪詢值4,我打電話Send後,還是有被卡在一個無限循環的危險嗎?


一些事實:

ServerXMLHTTPRequest可以使用waitForResponse內循環,但我想用XMLHTTPRequest組件。 據說那裏:

的waitForResponse的方法比輪詢 readyState屬性,這是等待使用XMLHTTP組件異步 發送的唯一途徑更有效。

回答

3

如果你擔心死循環,那麼簡單地實現你的循環超時,如:

var 
    xhttp: OleVariant; 
    Ticks: DWORD; 

    function TimeoutElapsed: Boolean; 
    var 
    Cur, Elapsed: DWORD; 
    begin 
    Cur := GetTickCount(); 
    if Cur >= Ticks then 
     Elapsed := Cur - Ticks 
    else 
     Elapsed := (MAXDWORD - Ticks) + Cur; 
    Result := (Elapsed >= 15000); 
    end; 

begin 
    xhttp := CreateOleObject('MSXML2.XMLHTTP'); 
    xhttp.Open('GET', URL, True); 
    xhttp.send(); 

    Ticks := GetTickCount(); 
    while (xhttp.readyState <> 4) and (not TimeoutElapsed()) do 
    begin 
    if MsgWaitForMultipleObjects(0, nil, False, 1000, QS_ALLINPUT) = WAIT_OBJECT_0 then 
     Application.ProcessMessages();   
    Ticks := GetTickCount(); 
    end; 

    // status property is available only when readyState is complete 
    if xhttp.readyState = 4 then 
    begin 
    if (xhttp.Status = 200) then... 
    end; 
end; 
+0

其實我是刨上增加一個超時這樣的(或多或少)。爲什麼我們需要MsgWaitForMultipleObjects,而不是使用Application.HandleMessage? – kobik 2011-12-28 23:18:14

+0

像你最初一樣在一個緊密的循環中調用'Application.ProcessMessages()',甚至'Application.HandleMessage()'不是一個好主意。這是非常低效的,並且已知會導致各種問題。 MsgWaitForMultipleObjects()可以告訴你什麼時候有未決的消息。當沒有任何東西需要處理時,調用'Application.ProcessMessages()'或'Application.HandleMessage()'沒有意義。 – 2011-12-29 00:05:35

+0

'MsgWaitForMultipleObjcts()'還會將調用線程置於有效睡眠狀態,直到消息到達或指定的超時時間結束,爲XMLHTTP對象提供更多時間片來完成其後臺工作。 – 2011-12-29 00:07:39