如何在超时的单独线程中发出HTTP请求?

时间:2010-03-18 07:26:36

标签: delphi http timeout multithreading request

我还没有在德尔福编程一段时间,坦率地说我不会想到...... 在这里,我拼命想找到关于这个问题的一些信息,现在它很稀缺,我找不到任何东西。所以也许你们可以帮助我。

目前我的应用程序使用Synapse库进行HTTP调用,但不允许设置超时。通常,这不是一个大问题,但现在我必须有一个超时来很好地处理任何连接问题。

我正在寻找的是一个库(同步或非同步),它允许HTTP请求对于没有可见或隐藏延迟的用户绝对透明。我现在不能立即杀死一个线程,并且可能会有许多频繁请求没有响应的服务器,这没有用。

编辑:谢谢大家的回答!

4 个答案:

答案 0 :(得分:3)

在进行网络通信时,您始终需要考虑延迟和超时。你可以获得最接近的IMHO是将网络通信放在一个线程中。然后你可以检查线程是否在所需的时间内完成,如果不是让它完成,但忽略结果(没有安全的方法来中止线程)。这还有一个额外的好处:您现在可以使用更容易阅读的同步网络调用。

答案 1 :(得分:2)

synapse中,TSynaClient对象可以使用THttpSend对象的超时时间。所以你需要做的就是调整超时(假设你使用标准函数)是复制你使用的函数,添加一个新参数并将Timeout设置为你需要的。例如:

function HttpGetTextTimeout(const URL: string; 
                            const Response: TStrings;
                            const Timeout:integer): Boolean;
var
  HTTP: THTTPSend;
begin
  HTTP := THTTPSend.Create;
  try
    HTTP.Timeout := Timeout;
    Result := HTTP.HTTPMethod('GET', URL);
    if Result then
      Response.LoadFromStream(HTTP.Document);
  finally
    HTTP.Free;
  end;
end;

Synapse默认为超时5000,如果您等待足够长时间,则会超时。由于其紧密包含,突触在线程中运行完美。

答案 2 :(得分:1)

[仅限于D2010工作]

您可以使用MSXML发送客户端请求(将msxmlole2添加到您的uses子句中。诀窍是使用IServerXMLHTTPRequest而不是IXMLHTTPRequest,因为前者允许指定超时。下面的代码显示了线程的Execute()方法:

procedure TClientSendThread.Execute;
const
  LResolveTimeoutMilliseconds = 2000;
  LConnectTimeoutMilliseconds = 5000;
  LSendTimeoutMilliseconds = 5000;
  LReceiveTimeoutMilliseconds = 10000;
var
  LHTTPServer: IServerXMLHTTPRequest;
  LDataStream: TMemoryStream;
  LData: OleVariant;
begin
  {Needed because this is inside a thread.}
  CoInitialize(nil);
  LDataStream := TMemoryStream.Create;
  try
    {Populate ....LDataStream...}
    LData := MemoryStreamToOleVariant(LDataStream);

    LHTTPServer := CreateOleObject('MSXML2.ServerXMLHTTP.3.0') as IServerXMLHTTPRequest;
    LHTTPServer.setTimeouts(
      LResolveTimeoutMilliseconds,
      LConnectTimeoutMilliseconds,
      LSendTimeoutMilliseconds,
      LReceiveTimeoutMilliseconds
      );
    LHTTPServer.open('POST', URL, False, 0, 0);
    LHTTPServer.send(LData);
    FAnswer := LHTTPServer.responseText;
  finally
    FreeAndNil(LDataStream);
    CoUninitialize;
  end;
end;

我最近发现了一种非常讨厌的MSXML技术行为,如果后续发送的URL保持不变,则不会重新发送GET个请求。换句话说,客户端正在缓存GET个请求。 POST不会发生这种情况。

显然,一旦超时发生,Execute方法就完成了,线程就被清理了。

答案 3 :(得分:0)

可以将Synapse配置为在发生网络错误时引发异常。

<强> RaiseExcept

检查http://synapse.ararat.cz/doc/help/blcksock.TBlockSocket.html#RaiseExcept

  

如果为True,则会出现winsock错误   例外。否则设置   只有LastError值,您必须   从你的程序检查它!默认   值为假。