【问题标题】:XMLHTTPRequest used asynchronously polling the readyStateXMLHTTPRequest 用于异步轮询 readyState
【发布时间】:2011-12-28 12:04:02
【问题描述】:

这是我的代码:

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

问题: 我调用Send 之后,在readyState 上轮询值4 是否安全,或者是否有陷入无限循环的风险?


一些事实:

ServerXMLHTTPRequest 可以在循环内使用waitForResponse,但我想使用XMLHTTPRequest 组件。 那里说:

waitForResponse 方法比轮询 readyState 属性,这是等待异步的唯一方法 使用 XMLHTTP 组件发送。

【问题讨论】:

    标签: c++ delphi xmlhttprequest


    【解决方案1】:

    如果您担心无限循环,那么只需为您的循环实现超时,例如:

    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;
    

    【讨论】:

    • 实际上我正计划添加这样的超时(或多或少)。为什么我们需要 MsgWaitForMultipleObjects,而不是使用 Application.HandleMessage?
    • 像您最初那样在一个紧密的循环中调用Application.ProcessMessages() 甚至Application.HandleMessage() 不是一个好主意。这是非常低效的,并且已知会导致各种问题。 MsgWaitForMultipleObjects() 可以告诉您何时有待处理的消息。当没有任何事情要处理时,调用Application.ProcessMessages()Application.HandleMessage() 是没有意义的。
    • MsgWaitForMultipleObjcts() 还将调用线程置于有效的睡眠状态,直到消息到达或指定的超时时间过去,从而为 XMLHTTP 对象提供更多时间片来完成其后台工作。
    • 如果您在主线程的上下文中调用它,那么可能是的,假设主消息队列中没有待处理的消息。如果在 1000 毫秒超时之前有消息到达队列,MsgWaitForMultipleObjects() 会立即唤醒。在循环中使用MsgWaitForMultipleObjects() 并不会改变循环本身阻塞调用线程的事实,它只是通过不必要地重复抽取消息队列来使循环更有效地工作,仅此而已。
    • 我认为循环内额外的Ticks := GetTickCount(); 会阻止循环在超时的情况下退出。还是我错过了什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 2012-02-29
    • 2017-09-09
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多