大约 4 天以来,我一直试图找出这个错误。我正在使用 Delphi XE,并创建了一个供翻译人员使用的小工具。我想到了使用 Microsoft 翻译 API 来帮助使事情变得更简单、不那么乏味。
我创建了一个访问 Microsoft 翻译 API 的类,但我想让它成为线程安全的,以便可以在后台发出请求。我发送请求以获取访问令牌没有问题,但是,我在单独的线程中运行该请求。当用户单击一个按钮时,我会生成一个新线程并运行 http 请求以从那里翻译该术语。但是,它每次都会超时。如果我从同一个线程运行它就没有问题。
这是我用于发送 http 请求的方法(传递的 THttpCli 对象在线程之间共享)
function sendHTTPRequest(APost: Boolean; AURI: UTF8string;
AContentType: UTF8string; APostData: UTF8String; AHttpCli: TSSLHttpCli): UTF8string;
var
DataOut: TMemoryStream;
DataIn: TMemoryStream;
lHTMLStream: TStringStream;
lencoding: TUTF8Encoding;
lownClient: boolean;
begin
lownClient := false;
if AHttpCli = nil then
begin
AHttpCli := TSSLHttpCli.Create(nil);
AHttpCli.SslContext := TSSLContext.Create(nil);
with AHttpCli.SslContext do
begin
SSLCipherList := 'ALL:!ADH:RC4+RSA:+SSLv2:@STRENGTH';
SSLVersionMethod := sslV23_CLIENT;
SSLVerifyPeerModes := [SslVerifyMode_PEER]
end;
AHttpCli.MultiThreaded := true;
lownClient := true;
end;
AHttpCli.Accept := 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
if APost then
begin
DataOut := TMemoryStream.Create;
DataOut.Write(APostData[1], Length(APostData));
DataOut.Seek(0, soFromBeginning);
end;
AHttpCli.URL := AURI;
AHttpCli.ContentTypePost := AContentType;
DataIn := TMemoryStream.Create;
if APost then AHttpCli.SendStream := DataOut;
AHttpCli.RcvdStream := DataIn;
try
if apost then
AHttpCli.Post
else
AHttpCli.Get;
lHTMLStream := TStringStream.Create('', TEncoding.UTF8);
lHtmlStream.LoadFromStream(AHttpCli.RcvdStream);
result := lHtmlStream.DataString;
lHtmlStream.Free;
finally
AHttpCli.Close;
AHttpCli.RcvdStream := nil;
AHttpCli.SendStream := nil;
DataIn.Free;
if APost then
DataOut.Free;
if lownClient then
AHttpCli.free;
end;
end;
我想显而易见的解决方案是只有一个线程等待信号执行,但我希望能解释为什么会发生超时。我无法解释为什么第二个线程超时而第一个线程没有。
HTTP 组件似乎卡在 dnslookup 上。OverbyteICS 使用 Windows 函数WSAAsyncGetHostByName
来查找名称。
任何帮助深表感谢
2013 年 5 月 13 日更新:
因此,事实证明,THttpCli
在线程之间共享对象似乎是导致超时的原因。解决方案只是将参数nil
传入AHttpCli
我上面的函数中。
我仍然会接受关于为什么会导致超时的答案。据我所知,该WSAAsyncGetHostByName
方法不使用任何同步对象,并且另一个线程没有同时运行,所以不应该有任何阻塞线程的东西。